我路过”系统标准输出作为进程的参数,然后进程写入系统标准输出“当它做它的事情。在
import multiprocessing
import sys
def worker_with(stream):
stream.write('In the process\n')
if __name__ == '__main__':
sys.stdout.write('In the main\n')
lock = multiprocessing.Lock()
w = multiprocessing.Process(target=worker_with, args=(sys.stdout,))
w.start()
w.join()
上面的代码不起作用,它返回以下错误:“ValueError:operation on closed file”。在
我试着运行相同的代码,但是直接调用函数而不是生成一个进程,它会输出到控制台。 我也尝试运行相同的代码,但直接调用系统标准输出在函数内部,将它作为一个进程生成,它就可以工作了。 问题似乎已经过去了系统结实作为过程的参数。在
有人知道为什么吗?在
注意:这段代码受教程PYMOTW-进程间通信的启发。在
编辑:我在Windows7上运行32位的Python2.7.10。在
当您将参数传递给
Process
时,它们在父对象中被pickle,传递给子对象,并在那里取消拾取。不幸的是,对于文件对象,pickle
的往返过程似乎会悄无声息地出错;对于协议0,它会出错,但是对于协议2(最高的Python 2协议,也是用于multiprocessing
)的协议),它会无声地生成一个垃圾文件对象:命名文件也会出现同样的问题;它不是标准句柄所特有的。基本上,
pickle
不能往返文件对象;即使它声称成功,结果也是垃圾。在一般来说,
multiprocessing
并不真的需要处理这样的场景;通常,Process
es是工作任务,I/O是通过主进程执行的(因为如果它们都独立地写入同一个文件句柄,则会出现交叉写入的问题)。在至少在Python3.5中,他们修复了这个问题,因此错误是即时的和明显的(由
open
、TextIOWrapper
和Buffered*
返回的类似文件的对象在使用任何协议pickle时都会出错)。在在Windows上,最好的方法是发送已知的文件描述符作为参数:
^{pr2}$然后在另一侧使用^{} 重新打开它。对于}}}{}})的标准处理的一部分,由于Windows使用“spawn”的“spawn”方法来产生新的{{>},因此,您需要确保任何这样的{{}是在{{}}{{})是在{{}}{{}{{{}{{{}{{{}}}{{}}{{}}}}}}{{{{{{}模块,将
fd
,由于0
,1
,1
,以及{{__name__
设置为其他值)。当然,如果它是一个命名文件,而不是一个标准句柄,你可以传递这个名称并重新打开它。例如,要使其生效,您需要更改:收件人:
注意:如前所述,如果
fd
是针对某个标准句柄,os.fdopen
将在with
语句退出时关闭底层文件描述符,这可能不是您想要的。如果您需要文件描述符在with
块关闭后继续存在,那么当传递一个文件描述符时,您可能需要在调用os.fdopen
之前使用{a2}来复制句柄,因此这两个句柄彼此独立。在其他解决方案包括通过
multiprocessing.Pipe
将结果写回主进程(因此主进程负责将数据传递给sys.stdout
,可能启动一个线程以异步执行此工作),或者使用更高级的构造(例如multiprocessing.Pool().*map*
),使用return
语句而不是显式文件I/O返回数据如果您真的很想让所有的文件描述符都能正常工作(并且不关心可移植性),而不仅仅是在} ,它用于显式地将文件描述符从一个进程复制到另一个进程;这将是令人难以置信的黑客行为(您需要查看
__main__
的import
上创建的标准句柄和描述符,那么您可以使用the undocumented Windows utility function ^{multiprocessing.forking.Popen
的其余Windows定义,以了解如何使用它),但它至少允许传递任意文件描述符,而不仅仅是静态打开的描述符。在相关问题 更多 >
编程相关推荐