这是来自Python.org的确切代码。如果您注释掉了time.sleep()
,它就会崩溃,并有一个长时间的异常回溯。,我想知道为什么,
而且,我理解为什么Python.org会将它包含在示例代码中。但是通过time.sleep()
人为地创建“工作时间”不应该在代码被删除时破坏代码。在我看来,time.sleep()
似乎提供了某种时间。但正如我所说,我想从那些真正知道答案的人那里知道。
一位用户评论要求我填写更多关于这种情况发生的环境的细节。它在OSX大南方11.4号上。使用来自Python.org的Python3.95的干净安装(不使用Homebrew等)。从Pycharm的内部运行在一个静脉中。我希望这有助于加深对局势的了解。
import time
import random
from multiprocessing import Process, Queue, current_process, freeze_support
#
# Function run by worker processes
#
def worker(input, output):
for func, args in iter(input.get, 'STOP'):
result = calculate(func, args)
output.put(result)
#
# Function used to calculate result
#
def calculate(func, args):
result = func(*args)
return '%s says that %s%s = %s' % \
(current_process().name, func.__name__, args, result)
#
# Functions referenced by tasks
#
def mul(a, b):
#time.sleep(0.5*random.random()) # <--- time.sleep() commented out
return a * b
def plus(a, b):
#time.sleep(0.5*random.random()). # <--- time.sleep() commented out
return a + b
#
#
#
def test():
NUMBER_OF_PROCESSES = 4
TASKS1 = [(mul, (i, 7)) for i in range(20)]
TASKS2 = [(plus, (i, 8)) for i in range(10)]
# Create queues
task_queue = Queue()
done_queue = Queue()
# Submit tasks
for task in TASKS1:
task_queue.put(task)
# Start worker processes
for i in range(NUMBER_OF_PROCESSES):
Process(target=worker, args=(task_queue, done_queue)).start()
# Get and print results
print('Unordered results:')
for i in range(len(TASKS1)):
print('\t', done_queue.get())
# Add more tasks using `put()`
for task in TASKS2:
task_queue.put(task)
# Get and print some more results
for i in range(len(TASKS2)):
print('\t', done_queue.get())
# Tell child processes to stop
for i in range(NUMBER_OF_PROCESSES):
task_queue.put('STOP')
if __name__ == '__main__':
freeze_support()
test()
如果它对任何人都有帮助,这就是回溯:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/spawn.py", line 126, in _main
self = reduction.pickle.load(from_parent)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/synchronize.py", line 110, in __setstate__
Traceback (most recent call last):
File "<string>", line 1, in <module>
self._semlock = _multiprocessing.SemLock._rebuild(*state)
FileNotFoundError: [Errno 2] No such file or directory
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/spawn.py", line 126, in _main
self = reduction.pickle.load(from_parent)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/synchronize.py", line 110, in __setstate__
self._semlock = _multiprocessing.SemLock._rebuild(*state)
FileNotFoundError: [Errno 2] No such file or directory
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/spawn.py", line 126, in _main
self = reduction.pickle.load(from_parent)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/synchronize.py", line 110, in __setstate__
self._semlock = _multiprocessing.SemLock._rebuild(*state)
FileNotFoundError: [Errno 2] No such file or directory
发布于 2021-06-10 05:46:43
这是一个技术故障。
这是一个主要进程结束的比赛条件,在一些孩子有机会完全启动之前就退出了。只要孩子完全开始工作,就有适当的机制确保他们顺利地关闭,但是中间时间是不安全的。竞争条件可能非常依赖于系统,因为这取决于操作系统和硬件来安排不同的线程,以及它们在工作中的速度。
当一个过程开始的时候.在创建子进程的早期,它会在主进程中注册自己,以便在主进程退出时(取决于它是否是守护进程(join
,multiprocessing.util._exit_function
)),它将是terminate
ed或terminate
d。此退出函数已在多进程导入的atexit
模块中注册。
在创建子进程期间,还会打开一对Pipe
,用于将Process
对象传递给子解释器(其中包括要执行的函数及其参数)。这需要与子节点共享两个文件句柄,并且这些文件句柄也被注册为使用atexit
关闭。
当主进程在子进程有机会在启动阶段读取管道中的所有必要数据(不对Process
对象进行筛选)之前退出时,就会出现问题。如果主进程首先关闭管道,然后等待子进程到join
,那么我们就有问题了。子实例将继续旋转新python实例,直到它需要读取包含函数和应该运行的参数的Process
对象。它将尝试从已经关闭的管道中读取,这是一个错误。
如果所有的孩子都有机会完全启动,你将永远不会看到这一点,因为这个管道只用于启动。拖延会在某种程度上保证所有的孩子都有时间完全开始,这才是解决这个问题的办法。手动调用join
将通过在调用任何atexit
处理程序之前等待子级来提供此延迟。此外,任何数量的处理延迟都意味着主线程中的q.get
必须等待一段时间,这也使子线程在关闭之前有时间启动。我从未能够重现您遇到的问题,但是您可能看到了所有TASKS
的输出(“Process-1表示mul(19,7) = 133 ")。只有一两个子进程完成了所有工作,允许主进程对所有结果进行get
,并在其他子进程完成启动之前完成。
编辑:
对于正在发生的事情,错误是明确的,但我仍然不知道它是如何发生的.据我所知,在_run_finalizers()
加入或终止所有active_children
之后,在中调用时,文件句柄应该关闭,而不是在通过_run_finalizers(0)
之前。
EDIT2:
_run_finalizers
似乎永远不会打电话给Popen.finalizer
关闭管道,因为exitpriority
是None
。我对这是怎么回事感到很困惑,我想我得好好想想.
https://stackoverflow.com/questions/67913861
复制相似问题