Python - 对关闭文件的子进程I/O操作

2 投票
3 回答
21687 浏览
提问于 2025-04-20 18:18

我用下面这个类尝试过,在Python 2.6中用subprocess模块按顺序执行命令。

from subprocess import Popen, PIPE

class BaculaActions():

    def __init__(self):
        self.console = Popen(["bconsole"], stdout=PIPE, stderr=PIPE, stdin=PIPE)

    def run_job(self, jobname, level):
        run = self.console.communicate("run job=%s level=%s yes" % (jobname, level))
        return(run)

    def del_jobid(self, jobid):
        delete = self.console.communicate("delete jobid=%s" % (jobid))
        return(delete)

但是,如果我尝试以下代码,就会出现错误: ValueError: 在关闭的文件上进行I/O操作。

from pconsole import BaculaActions

myconsole = BaculaActions()

run = myconsole.run_job("xxxxx-data", "incremental")
delete = myconsole.del_jobid(25487)

有人知道可能出什么问题了吗? 谢谢!

3 个回答

-2

更好的做法是这样:

任何子进程的初始化都应该用“try catch”来包裹,这样可以处理资源分配失败的情况。如果成功了,就返回结果。

在进行通信之前,先检查一下通道是否已经建立(没有错误),然后再进行通信。

最好的方法是把“Popen”放在你进行通信的同一个地方。这样可能会导致你重复使用“Popen”两次,但这样做是安全的。

在“Popen”和“communicate”之间,如果出现任何未知的中断,可能会导致你的Python程序一直挂着,需要手动结束。这是我们在实际操作中绝对不想发生的情况。

1

感谢所有曾经尝试帮助我的人。

作为解决这个问题的方法,我做了以下事情:

class BaculaActions():

    def console(self):
        return(Popen(["bconsole"], stdout=PIPE, stderr=PIPE, stdin=PIPE))

    def run_job(self, jobname, level):
        run = self.console().communicate("run job=%s level=%s yes" % (jobname, level))
        return(run)

    def del_jobid(self, jobid):
        delete = self.console().communicate("delete jobid=%s" % (jobid))
        return(delete)

    def any_commands(self, command):
        any = self.console().communicate(command)
        return(any)

我创建了一个叫“console”的方法,然后在我的类中的其他所有方法开始时都调用这个方法。

这样就解决了我的问题。

谢谢大家!

5

手册上其实说得很清楚:

Popen.communicate(input=None, timeout=None)
Interact with process: Send data to stdin. Read data from stdout and stderr, 
until end-of-file is reached. Wait for process to terminate.

当你运行第一个命令并得到结果后,'bconsole'这个过程就已经结束了,管道也关闭了,所以在第二次调用communicate时就会出现错误。

撰写回答