我在嘗試讓 Thread (threading.Thread) 子類在 Process (multiprocessing.Process) 子類中作業時遇到了麻煩。
這是演示該問題的最簡單的作業示例。我制作了一個“SubProcess”(multiprocessing.Process 的實體),它將包含一個子“WorkerThread”(threading.Thread 的實體)。執行終止于subProcess.start()
import multiprocessing
import threading
class SubProcess(multiprocessing.Process):
def __init__(self):
multiprocessing.Process.__init__(self, daemon=True)
#Instantiate this one worker
self.workerThread = WorkerThread()
def run(self):
#Start the worker
self.workerThread.start()
class WorkerThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self, daemon=True)
def run(self):
#Real work code goes here
pass
if __name__ == '__main__':
#Program starts here
#Instantiate the SubProcess class - works fine
subProcess = SubProcess()
#Start the subProcess - Execution stops here - see Traceback below
subProcess.start()
subProcess.join()
這是輸出回溯:
Traceback (most recent call last):
File "[***]\simplestExampleError.py", line 31, in <module>
subProcess.start()
File "C:\Python39\lib\multiprocessing\process.py", line 121, in start
self._popen = self._Popen(self)
File "C:\Python39\lib\multiprocessing\context.py", line 224, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "C:\Python39\lib\multiprocessing\context.py", line 327, in _Popen
return Popen(process_obj)
File "C:\Python39\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
reduction.dump(process_obj, to_child)
File "C:\Python39\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle '_thread.lock' object
[***]>Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Python39\lib\multiprocessing\spawn.py", line 107, in spawn_main
new_handle = reduction.duplicate(pipe_handle,
File "C:\Python39\lib\multiprocessing\reduction.py", line 79, in duplicate
return _winapi.DuplicateHandle(
PermissionError: [WinError 5] Access is denied
我已經回顧了這個類似的問題,但關鍵的區別在于它們定義了“WorkerThread”來指向一個函式,并帶有預定義的引數(不是“threading.Thread”的子類)。
示例:在子流程中,他們定義workerThread = Thread(target=print_all_the_things, args=("a", self.num))
I require the ability to change the WorkerThread's class variables while it is running.
Example: In the subProcess, I would do something like self.workerThread.input = "INPUT" while both are running
Any help would be greatly appreciated!
uj5u.com熱心網友回復:
我沒有看到您發布的代碼有任何理由(當然,您只發布了非常少的代碼)為什么需要在SubProcess.__init__方法中完成作業執行緒的實體化。我會簡單地workerThread在run方法中初始化屬性:
class SubProcess(multiprocessing.Process):
def __init__(self):
multiprocessing.Process.__init__(self, daemon=True)
def run(self):
#Instantiate this one worker
self.workerThread = WorkerThread()
#Start the worker
self.workerThread.start()
我不認為這是一個致命的缺陷,從派生的類Process和Thread類,但它不是很靈活。如果使用您的SubProcess類的代碼想要為行程分配名稱屬性怎么辦?在您當前的實作中,您必須重新設計__init__方法。下面的實作更簡潔,使類可在非多處理、非多執行緒場景中重用(為此我可能會選擇不同的方法名稱,而不是run更好地描述方法完成的處理):
import multiprocessing
import threading
class SubProcess:
def __init__(self):
# set whatever attributes are required (that can be pickled)
...
def run(self): # or a more descriptive method name
#Instantiate this one worker
worker = Worker()
self.workerThread = threading.Thread(target=worker.run, daemon=True)
#Start the worker
self.workerThread.start()
class Worker:
def __init__(self):
# set whatever attributes are required
...
def run(self): # or a more descriptive method name
#Real work code goes here
pass
if __name__ == '__main__':
subprocess = SubProcess()
# In this context, the Process does not need to be a daemon process
# since we are waiting for its complettion:
p = mulitprocessing.Process(target=subprocess.run, name='SubProcess')
p.start()
p.join()
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/335992.html
標籤:python multithreading multiprocessing
