How to keep process without "main thread" in python3 multiprocessing? - python-3.x

Multiprocessing in python starts a new process.
Within that new process, I create 2 new threads and do nothing else in the "main thread" that started the new process, it seems that the process is gone.
Example:
new_process = multiprocessing.Process(target=new_proc_main, name=yyy)
new_process.start()
def new_proc_main():
thread1 = threading.Thread(target=xxxx, name=thread1)
thread1.start()
thread2 = threading.Thread(target=xxxx, name=thread2)
thread2.start()
How can I keep the new process alive while threads 1 & 2 run?

I wrote a test program. This is Python 3.6.2 on MacOS
import multiprocessing
import time
def new_main():
import threading
my_thread = threading.Thread(target=dummy_main)
my_thread.start()
my_thread.join()
def dummy_main():
while True:
print("thread running")
time.sleep(1)
print("start process")
p = multiprocessing.Process(target=new_main)
p.start()
The key is that I have to have my_thread.join().
If I do not have that, the program exits immediately.

Related

python3 - Main thread kills child thread after some timeout?

I'm not sure it is doable with thread in python. Basically, I have a function which invokes GDAL library to open an image file. But this can be stuck, so, after 10 seconds, if the file cannot be opened, then it should raise an exception.
import threading
import osgeo.gdal as gdal
def test(filepath):
# After 10 seconds, if the filepath cannot be opened, this function must end and throw exception.
# If the filepath can be opened before 10 seconds, then it return dataset
dataset = gdal.Open(filepath)
return dataset
filepath="http://.../test.tif"
t = threading.Thread(target = test, args = [filepath])
t.start()
# is there something called t.timeout(10)
# and if this thread cannot be finished in 10 seconds, it raises a RuntimeException?
t.join()
I ended up using multiprocessing and Queue from multiprocessing to achieve what I wanted:
import multiprocessing
import time
from multiprocessing import Queue
q = Queue()
TIME_OUT = 5
def worker(x, queue):
time.sleep(15)
a = (1, 5, 6, 7)
queue.put(a)
queue = Queue()
process = multiprocessing.Process(target=worker, args=(5, queue,))
process.start()
# main thread waits child process after TIME_OUT
process.join(TIME_OUT)
if process.is_alive():
print("Process hangs!")
process.terminate()
print("Process finished")
print(queue.qsize())
if queue.qsize() > 0:
a, b, _, d = queue.get()
print(a, b, d)

In PyGTK, how to start thread and continue calling function only when thread terminates

After reading many questions about threads and .join() function, I still can not find how to adapt the basic pygobject threads example from documentation, so that it matches my use case:
#!/bin/python3
import threading
import time
from gi.repository import GLib, Gtk, GObject
def app_main():
win = Gtk.Window(default_height=50, default_width=300)
win.connect("destroy", Gtk.main_quit)
def update_progess(i):
progress.pulse()
progress.set_text(str(i))
return False
def example_target():
for i in range(50):
GLib.idle_add(update_progess, i)
time.sleep(0.2)
def start_actions(self):
print("do a few thing before thread starts")
thread = threading.Thread(target=example_target)
thread.daemon = True
thread.start()
print("do other things after thread finished")
mainBox = Gtk.Box(spacing=20, orientation="vertical")
win.add(mainBox)
btn = Gtk.Button(label="start actions")
btn.connect("clicked", start_actions)
mainBox.pack_start(btn, False, False, 0)
progress = Gtk.ProgressBar(show_text=True)
mainBox.pack_start(progress, False, False, 0)
win.show_all()
if __name__ == "__main__":
app_main()
Gtk.main()
How to make this code print "do other things after thread finished" only after my thread terminates and without freezing main window?
First, just to make it clear, the thread isn't finished after you call its start method.
Look at the definition of the code running in the thread:
def example_target():
for i in range(50):
GLib.idle_add(update_progess, i)
time.sleep(0.2)
What this does is basically repeat the following 50 times:
tell GTK to execute update_progress at the next time the system is idle (has no events to process).
sleeps for 0.2 seconds.
You could define a function after_thread, and have that scheduled when the thread finishes:
def example_target():
for i in range(50):
GLib.idle_add(update_progess, i)
time.sleep(0.2)
# loop is finished, thread will end.
GLib.idle_add(after_thread)

how to stop input() from main thread in python3

What should be written in kill_input() instead of pass to stop input() and terminate the program?
#!/usr/bin/env python3
import threading, time
running = True
def kill_input():
pass
def input_reader():
while running:
print(input())
t = threading.Thread(target = input_reader)
t.start()
time.sleep(2)
kill_input()
print('bye')
Solved with setting the thread to daemon.
t.daemon = True
t.start()
If there are no hanging non-daemon threads it will terminate automatically.

Stop multiples threads if error ocurred and keep running the main thread ? Python

Is there a way to stop all threads in the list if an error occurs in any of them without stopping the main thread ?
from threading import Thread
def build_packages(pkg_id):
try:
# do something
except Exception:
# stop all threads except main thread
threads = []
for pkg_id in pkgs:
t = Thread(target=build_packages, args=[pkg_id])
threads.append(t)
t.setDaemon(True)
t.start()
for t in threads:
t.join()

How to properly quit a QThread in PyQt5 when using moveToThread

I am trying to quit a thread after it is done processing. I am using moveToThread. I'm trying to quit the worker thread from the main thread by calling self.thread.quit() in the slot. And that's not working.
I've found several examples of starting the thread using moveToThread, such as this one. But I can't find how to quit one.
from PyQt5.QtCore import QObject, QThread
from PyQt5.QtCore import pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
print("Base init")
self.start_thread()
#pyqtSlot(int)
def onFinished(self, i):
print("Base caught finished, {}".format(i))
self.thread.quit()
print('Tried to quit thread, is the thread still running?')
print(self.thread.isRunning())
def start_thread(self):
self.thread = QThread()
self.w = Worker()
self.w.finished1[int].connect(self.onFinished)
self.w.moveToThread(self.thread)
self.thread.started.connect(self.w.work)
self.thread.start()
class Worker(QObject):
finished1 = pyqtSignal(int)
def __init__(self):
super().__init__()
print("Worker init")
def work(self):
print("Worker work")
self.finished1.emit(42)
if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
This is the output from all my print functions (without the color of course):
Base init
Worker init
Worker work
Base caught finished, 42
Tried to quit thread, is the thread still running?
True
Try running your script multiple times. Is the result of the call to self.thread.isRunning() always the same? Try adding a call to time.sleep(1) before checking if the thread is still running. Notice any difference?
Remember that you are making a call from the main thread of your program, to another thread, which is by definition asynchronous. Your program will not wait to make sure self.thread.quit() has completed before executing the next instructions.
same as answer above but showing option 2
that is using QThread.wait() :
https://doc.qt.io/qtforpython/PySide6/QtCore/QThread.html#PySide6.QtCore.PySide6.QtCore.QThread.wait :
Blocks the thread until either of these conditions is met:
The thread associated with this QThread object has finished execution (i.e. when it returns from run() ). This function will return true if the thread has finished. It also returns true if the thread has not been started yet.
The deadline is reached. This function will return false if the deadline is reached.
A deadline timer set to QDeadlineTimer::Forever (the default) will never time out: in this case, the function only returns when the thread returns from run() or if the thread has not yet started.
from PyQt5.QtCore import QObject, QThread
from PyQt5.QtCore import pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QMainWindow
import time
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
print("Base init")
self.start_thread()
#pyqtSlot(int)
def onFinished(self, i):
print("Base caught finished, {}".format(i))
self.thread.quit()
print('Tried to quit thread, is the thread finished ? : ', self.thread.isFinished())
print('Tried to quit thread, is the thread still running? : ', self.thread.isRunning())
# # option 1
# print( '\nafter time.sleep(2)')
# time.sleep(2)
# print('Tried to quit thread, is the thread finished ? : ', self.thread.isFinished())
# print('Tried to quit thread, is the thread still running? : ', self.thread.isRunning())
# option 2
self.thread.wait()
print( '\nafter thread.wait()')
print('Tried to quit thread, is the thread finished ? : ', self.thread.isFinished())
print('Tried to quit thread, is the thread still running? : ', self.thread.isRunning())
def start_thread(self):
self.thread = QThread()
self.w = Worker()
self.w.finished1[int].connect(self.onFinished)
self.w.moveToThread(self.thread)
self.thread.started.connect(self.w.work)
self.thread.start()
class Worker(QObject):
finished1 = pyqtSignal(int)
def __init__(self):
super().__init__()
print("Worker init")
def work(self):
print("Worker work")
self.finished1.emit(42)
if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
output #option 1 sleep :
Base init
Worker init
Worker work
Base caught finished, 42
Tried to quit thread, is the thread finished ? : False
Tried to quit thread, is the thread still running? : True
after time.sleep(2)
Tried to quit thread, is the thread finished ? : True
Tried to quit thread, is the thread still running? : False
output #option 1 wait :
Base init
Worker init
Worker work
Base caught finished, 42
Tried to quit thread, is the thread finished ? : False
Tried to quit thread, is the thread still running? : True
after thread.wait()
Tried to quit thread, is the thread finished ? : True
Tried to quit thread, is the thread still running? : False

Resources