首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >不使用time.sleep()时Python多处理怪异行为

不使用time.sleep()时Python多处理怪异行为
EN

Stack Overflow用户
提问于 2021-06-10 02:30:34
回答 2查看 682关注 0票数 0

这是来自Python.org的确切代码。如果您注释掉了time.sleep(),它就会崩溃,并有一个长时间的异常回溯。,我想知道为什么,

而且,我理解为什么Python.org会将它包含在示例代码中。但是通过time.sleep()人为地创建“工作时间”不应该在代码被删除时破坏代码。在我看来,time.sleep()似乎提供了某种时间。但正如我所说,我想从那些真正知道答案的人那里知道。

一位用户评论要求我填写更多关于这种情况发生的环境的细节。它在OSX大南方11.4号上。使用来自Python.org的Python3.95的干净安装(不使用Homebrew等)。从Pycharm的内部运行在一个静脉中。我希望这有助于加深对局势的了解。

代码语言:javascript
运行
复制
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()

如果它对任何人都有帮助,这就是回溯:

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

回答已采纳

发布于 2021-06-10 05:46:43

这是一个技术故障。

这是一个主要进程结束的比赛条件,在一些孩子有机会完全启动之前就退出了。只要孩子完全开始工作,就有适当的机制确保他们顺利地关闭,但是中间时间是不安全的。竞争条件可能非常依赖于系统,因为这取决于操作系统和硬件来安排不同的线程,以及它们在工作中的速度。

当一个过程开始的时候.在创建子进程的早期,它会在主进程中注册自己,以便在主进程退出时(取决于它是否是守护进程(joinmultiprocessing.util._exit_function)),它将是terminateed或terminated。此退出函数已在多进程导入的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关闭管道,因为exitpriorityNone。我对这是怎么回事感到很困惑,我想我得好好想想.

票数 2
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67913861

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档