如何创建子流程可以读取的临时文件? 我正在编写一个Python脚本,需要将一些数据写入一个临时文件,然后创建一个运行C++文件的子进程,该程序将读取临时文件。我想用这个,但根据文件
在命名的临时文件仍处于打开状态时,该名称是否可用于再次打开该文件,因平台而异(在Unix上可以使用该名称;在Windows NT或更高版本上不能使用该名称) 事实上,在Windows上,如果我在写入后刷新临时文件,但在希望它消失之前不要关闭它,则子进程将无法打开它进行读取 我通过使用如何创建子流程可以读取的临时文件? 我正在编写一个Python脚本,需要将一些数据写入一个临时文件,然后创建一个运行C++文件的子进程,该程序将读取临时文件。我想用这个,但根据文件,python,windows,temporary-files,Python,Windows,Temporary Files,在命名的临时文件仍处于打开状态时,该名称是否可用于再次打开该文件,因平台而异(在Unix上可以使用该名称;在Windows NT或更高版本上不能使用该名称) 事实上,在Windows上,如果我在写入后刷新临时文件,但在希望它消失之前不要关闭它,则子进程将无法打开它进行读取 我通过使用delete=False创建文件来解决这个问题,在生成子流程之前关闭它,然后在完成后手动删除它: fileTemp = tempfile.NamedTemporaryFile(delete = False) try:
delete=False
创建文件来解决这个问题,在生成子流程之前关闭它,然后在完成后手动删除它:
fileTemp = tempfile.NamedTemporaryFile(delete = False)
try:
fileTemp.write(someStuff)
fileTemp.close()
# ...run the subprocess and wait for it to complete...
finally:
os.remove(fileTemp.name)
这似乎不雅。有更好的方法吗?也许有一种方法可以打开临时文件的权限,以便子进程可以访问它?您可以始终使用低级,但我不确定它是否足够干净:
fd, filename = tempfile.mkstemp()
try:
os.write(fd, someStuff)
os.close(fd)
# ...run the subprocess and wait for it to complete...
finally:
os.remove(filename)
至少如果您使用现有的Python库打开临时文件,那么在Windows中,从多个进程访问它是不可能的。根据,您可以指定第三个参数(
dwSharedMode
)共享模式标志FILE\u SHARE\u READ
到CreateFile()
函数,该函数:
启用文件或设备上的后续打开操作以请求读取
通道否则,其他进程无法打开文件或设备,如果
它们请求读取访问权限。如果未指定此标志,但文件
或设备已打开进行读取访问,则功能失败
因此,您可以编写一个特定于Windows的C例程来创建一个自定义的临时文件开启器函数,从Python中调用它,然后您可以让您的子进程无错误地访问该文件。但我认为您应该坚持现有的方法,因为它是最可移植的版本,可以在任何系统上工作,因此是最优雅的实现
- 可以找到关于Linux和windows文件锁定的讨论
NamedTemporaryFile
失败的唯一原因是
Windows是因为当我们重新打开时,我们需要使用O_TEMPORARY
他给出了一个在Python3.3中如何实现这一点的示例+
import os, tempfile
DATA = b"hello bob"
def temp_opener(name, flag, mode=0o777):
return os.open(name, flag | os.O_TEMPORARY, mode)
with tempfile.NamedTemporaryFile() as f:
f.write(DATA)
f.flush()
with open(f.name, "rb", opener=temp_opener) as f:
assert f.read() == DATA
assert not os.path.exists(f.name)
由于Python 2.x中内置的open()
函数中没有opener
参数,因此我们必须将较低级别的os.open()
函数和os.fdopen()
函数组合起来以达到相同的效果:
import subprocess
import tempfile
DATA = b"hello bob"
with tempfile.NamedTemporaryFile() as f:
f.write(DATA)
f.flush()
subprocess_code = \
"""import os
f = os.fdopen(os.open(r'{FILENAME}', os.O_RDWR | os.O_BINARY | os.O_TEMPORARY), 'rb')
assert f.read() == b'{DATA}'
""".replace('\n', ';').format(FILENAME=f.name, DATA=DATA)
subprocess.check_output(['python', '-c', subprocess_code]) == DATA
因为似乎没有其他人有兴趣公开这些信息
tempfile
确实公开了一个函数,mkdtemp()
try:
temp_dir = mkdtemp()
temp_file = make_a_file_in_a_dir(temp_dir)
do_your_subprocess_stuff(temp_file)
remove_your_temp_file(temp_file)
finally:
os.rmdir(temp_dir)
我将中间函数的实现留给读者,因为读者可能希望使用mkstemp()
之类的方法来加强临时文件本身的安全性,或者在删除之前覆盖文件。我不知道有哪些安全限制是不容易通过阅读tempfile
的源代码来计划的
无论如何,是的,在Windows上使用NamedTemporaryFile
可能不雅观,我的解决方案也可能不雅观,但您已经决定Windows支持比优雅的代码更重要,因此,您不妨继续做一些可读的事情。您是否考虑过将流程管道化作为一种可能性?@JonClements是的,管道化也是可能的,但它需要更改子流程的接口,我希望避免这种情况。相关:Python问题14243-另请参阅Linux的解决方案:谢谢。我希望pythonapi能够公开这些模式标志,但我想我可以理解为什么它们不公开。好吧,至少如果您使用现有的Python库打开一个临时文件,那么在Windows环境下,从多个进程访问它是不可能的。那不是真的。请参阅和my.interest…我使用的是Python 2.x,但我必须进一步研究这一点。@NathanReed在Python 2.x中也可以这样做-请参阅我的更新。请注意,这仅在您控制子流程中的代码时有效。调用像tar
这样的系统实用程序并不是件容易的事。尽管如此,我还是找到了@尤瑟仔细看;显示的页面中每组常量的标签位于该组下,而不是上方。如果控制子流程的代码,这是最佳解决方案。如果没有,我看不到比原始问题更优雅的解决方案。清理代码可以用shutil.rmtree(temp\u dir)
简化,我可能会弄错,但这看起来是最好的答案。小心!这根本不能回答最初的问题。这不仅不比OP已经在做的事情好,而且更糟糕的是将创建临时文件的脆弱方面留给用户–在临时目录(temp\u dir)中创建临时文件
。请参阅我的答案,以获得更好的处理方法。(我不明白为什么我在四年前第一次读到这篇文章时没有写下这篇评论…)投反对票。尽管此答案提出了原始问题的解决方案(在子流程中打开临时文件),但这并不是比原始问题中包含的答案更优雅的答案,因为此答案使用较低级别的函数,并且忽略了一般的临时文件问题(例如安全性)赋值前引用的局部变量“temp\u dir”
。我猜实际的创建必须要退出“尝试”,这使得调试它很困难?