如何在Python上实现多处理



我正在Python中制作一个小程序,使用tkinter来移动多个对象。

首先,我尝试线程化来创建两个对象,并使它们同时移动。因此,我复制/粘贴创建和移动1个对象的函数,然后在2个线程中执行这两个函数。

现在我想尝试选择移动对象的数量,所以我得到了1个函数,我想同时执行它多次。线程不再是可能的。

所以我尝试了多处理,但我遇到了一个问题:它什么都不做。。。我用一个简单的代码重新创建了这个问题:

import multiprocessing
def pr(number):
print(number)
p = multiprocessing.Process(target=pr,args=(40,))
p.start()

它返回一个绝对的"无",不打印任何内容。我认为多处理不是做我想做的事情的合适工具,但我不理解这段代码的问题。

PS:我在Windows 上使用IDLE Python 3.7.2

这篇文章本质上是可以从IDLE运行多处理进程类的副本。我在SO中搜索";[python idle]多处理";。我在这里给出了我之前答案的修订和扩展版本。

  1. 正如@Booboo所说,至少在Windows和macOS上需要if __name __ == '__main__':块。在这种情况下,multiprocessing本身在Windows上从IDLE启动时运行良好。

  2. 失败在于打印。当multiprocessing启动一个新的python进程时,它会将当前进程sys.__stdout__复制到新进程中的sys.__stdout__sys.stdout。默认情况下,print将请求的文本写入sys.stdout

当GUI程序从图标或以某种方式而非终端启动时,sys.__stdout__sys.stdout会初始化为None,至少在Windows上是这样。IDLE将sys.stdout替换为一个对象,该对象的write方法将文本发送到IDLE的Shell。复制IDLE特定的sys.stdout是没有用的,因为它不起作用。

如果在Windows上使用py -m idlelib从命令行启动IDLE,则sys属性将初始化为一个普通的python-io对象,该对象将文本发送到控制台/终端。IDLE只替换sys.stdout,因此多处理可以将工作的sys.__stdout__io对象复制到新进程的两个sys属性中。默认情况下,"print"将打印到控制台,如本例所示。

import multiprocessing, sys
def pr():
print(sys.stdout)
if __name__ == '__main__':
p = multiprocessing.Process(target=pr)
p.start()
p.join()
# Writes the following to the 
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>

打印到CommandPrompt显然不太好,但这是使用非IDLE代码所能做的最好的操作。在您的特定情况下,想要对tkinter对象设置动画(可能是在tkinter画布上(,您应该在循环后使用tk/tkinter,而不是多处理。IDLE是为开发tkinter程序而设计的。在SO中搜索[tkinter] animate可以得到几百次点击。

正如Terry Jan Reedy所指出的,我关于不能在IDLE下运行多处理的评论显然是错误的。

IDLE的问题与在Jupyter Notebook等环境中尝试进行多处理时遇到的问题相同。也就是说,除了您的辅助函数pr必须在导入的单独模块中之外,还可以执行此操作。如果你不这样做,那么你会得到以下异常:

AttributeError: Can't get attribute 'pr' on <module '__main__' (built-in)>

不幸的是,通过从Windows开始菜单启动IDLE,从未看到该异常消息。如果IDLE是从命令提示符启动的,而不是用。。。

python -m idlelib

则CCD_ 19异常将显示在命令提示符控制台上。

因此:

  1. pr函数放在某个目录中的文件中,例如pr.py
  2. 打开命令提示符,将当前目录更改为包含pr.py的目录
  3. 使用python-m idlelib启动IDLE

然后您的程序变成:

import multiprocessing
from pr import pr

if __name__ == '__main__': # required for Windows
p = multiprocessing.Process(target=pr,args=(40,))
p.start()
p.join() # Wait for the completion explicitly

相关内容

  • 没有找到相关文章

最新更新