在Windows上使用多处理似乎任何打开的文件句柄都由生成的进程继承。这有锁定它们的令人不快的副作用。
我对两者都感兴趣:
1)防止继承
2)从生成的进程中释放文件的方法
考虑以下代码在OSX上运行正常,但在os.rename
上的窗口崩溃from multiprocessing import Process
import os
kFileA = "a.txt"
kFileB = "b.txt"
def emptyProcess():
while 1:
pass
def main():
# Open a file and write a message
testFile = open(kFileA, 'a')
testFile.write("Message One\n")
# Spawn a process
p = Process(target=emptyProcess)
p.start()
# Close the file
testFile.close()
# This will crash
# WindowsError: [Error 32] The process cannot access the file
# because it is being used by another process
os.rename(kFileA, kFileB)
testFile = open(kFileA, 'a')
testFile.write("Message Two\n")
testFile.close()
p.terminate()
if __name__ == "__main__":
main()
答案 0 :(得分:4)
fileno()
方法返回运行时库分配的文件号。根据文件编号,您可以调用msvcrt.get_osfhandle()
来获取Win32文件句柄。在调用SetHandleInformation
时使用此句柄。所以类似下面的内容可能会起作用:
win32api.SetHandleInformation(
msvcrt.get_osfhandle(testFile.fileno()),
win32api.HANDLE_FLAG_INHERIT,
0)
我不确定win32api
模块的确切用法,但这应该有助于弥合Python文件对象和Win32句柄之间的差距。
答案 1 :(得分:1)
我不知道多处理模块,但是使用subprocess模块可以指示它不继承任何文件描述符:
如果close_fds为true,则在执行子进程之前将关闭除0,1和2之外的所有文件描述符。 (仅限Unix)。或者,在Windows上,如果close_fds为true,则子进程不会继承任何句柄。请注意,在Windows上,您不能将close_fds设置为true,还可以通过设置stdin,stdout或stderr来重定向标准句柄。
或者,您可以使用os.closerange
关闭子流程中的所有文件描述符将所有文件描述符从fd_low(包括)关闭到fd_high(不包括),忽略错误。可用性:Unix,Windows。
答案 2 :(得分:0)
打开文件句柄后,可以使用SetHandleInformation()函数删除HANDLE_FLAG_INHERIT
标志。
答案 3 :(得分:0)
使用旋转日志和多处理时遇到此问题。当父进程尝试旋转日志时,它会以
失败WindowsError:[错误32]进程无法访问该文件,因为它正被另一个进程
使用
基于其他一些答案,以下是python 2.7中的工作解决方案,以防止日志文件处理程序被继承
fd = logging.getLogger().handlers[0].stream.fileno() # The log handler file descriptor
fh = msvcrt.get_osfhandle(fd) # The actual windows handler
win32api.SetHandleInformation(fh, win32con.HANDLE_FLAG_INHERIT, 0) # Disable inheritance
请注意这个问题在python 3.4中有所涉及。有关详情,请参阅 https://www.python.org/dev/peps/pep-0446/