在 subprocess.Popen 中关闭标准输入
Posted
技术标签:
【中文标题】在 subprocess.Popen 中关闭标准输入【英文标题】:Closing stdin in subprocess.Popen 【发布时间】:2014-04-24 21:12:44 【问题描述】:假设我编写了以下函数。现在的问题是另一个函数使用 voronoi.out 文件作为输入。我不知道在 sp.Popen 完成后如何关闭这个标准输入。如果我不这样做,qvoronoi 程序会“挂起”直到我的脚本结束,并且下一个函数无法读取这个 voronoi.out 文件。
def voronoi(self):
''' This function calls qvoronoi program to create
file with vertices.'''
self.inp=open(self.out_name, 'r') #Redirect input and output for qvoronoi script
self.out=open('voronoi.out', 'w')
sp.Popen(['./qvoronoi', 'p', 'FN'], stdin=self.inp, stdout=self.out) #Execute qvoronoi
self.out.close() #Safely close output file
【问题讨论】:
尚不清楚使用self.out.close()
关闭文件是否有效。如果是,那是什么问题?
注意:您可以在此处使用subprocess.check_call
而不是Popen
。 check_call
调用 .wait()
方法并在返回非零退出状态时引发异常(0
状态表示成功)。 code example
【参考方案1】:
主要问题是您没有等待程序退出。当您的函数退出时,qvoronio 仍在使用该文件,因此其他人可能会被阻止。而且由于您不等待,qvoronio 在执行完成后仍处于“僵尸”状态,这可能看起来像是挂起。此外,您将临时 inp/outp 文件句柄放在自己的对象上,实际上,您想立即关闭它们。
更多热心的pythonistas喜欢使用上下文管理器来确保文件被正确关闭,并且可能会做这样的事情:
def voronoi(self):
with open(self.out_name, 'r') as inp:
with open('voronoi.out', 'w') as outp:
qvoronio = sp.Popen(['./qvoronoi', 'p', 'FN'], stdin=inp, stdout=oup)
qvoronio.wait()
请注意,在上下文管理器退出后等待已完成。将文件交给子后,您已关闭父级中的文件。
我通常这样做:
def voronoi(self):
qvoronio = sp.Popen(['./qvoronoi', 'p', 'FN'], stdin=open(self.out_name, 'r'),
stdout=open('voronoi.out', 'w'))
qvoronio.wait()
并遭受纯粹主义者的愤怒。我的方法适用于 cpython,但可能会在其他变体中卡住你。
【讨论】:
@J.F.Sebastian - 我的 python 3.2 没有,这是在更高版本中吗?我承认我在这里是老派,当 Popen 调用返回时文件句柄有 0 个引用,并且过去通常意味着对象被删除并且文件被关闭。 垃圾收集使代码的推理变得非常困难。我更喜欢显式的资源管理。ResourceWarning
在 Python 3.2 中添加。我不知道何时/如何为文件启用它。
这是不受欢迎的,因为 Python 规范不保证引用计数的实现。
@Lucretiel - 我认为 python 接受引用计数的外语观点太糟糕了,这使得实现的确定性降低并增加了代码复杂性,因为 with
语句层次结构是不可取的。当范围退出时,本地资源不会自动清理,我发现这是糟糕的设计。所以,我遭受了愤怒......虽然我认为我是纯粹主义者!
考虑到@tdelaney 的论述风格,我不得不承认,虽然他有一点要说——Python 是作为一种通用语言和基于范围的自动化资源而创建的解除分配仅适用于非常基本的问题。在我看来,这种直接、绝对缺乏任何神奇的实用主义 - 正是 Python 在今天如此受欢迎和接受的原因。以上是关于在 subprocess.Popen 中关闭标准输入的主要内容,如果未能解决你的问题,请参考以下文章
将标准输出从 subprocess.Popen 保存到文件,并将更多内容写入文件
如何从 subprocess.Popen 使用 STDIN [重复]