【问题标题】:Python - subprocess I/O operation on closed filePython - 对已关闭文件的子进程 I/O 操作
【发布时间】:2014-09-09 21:46:55
【问题描述】:

我试过下面的类,在python2.6中用subporcess模块​​按顺序执行命令。

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)

任何人都知道什么是错的? 谢谢

【问题讨论】:

    标签: python subprocess


    【解决方案1】:

    手册确实说明了一切:

    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 调用出现错误。

    【讨论】:

    • @isdeve 这样的话,唯一的解决方案是对于我需要运行的每个命令,我再次实例化“mysconsole”?另一个疑问,由于 Popen 没有“方法”关闭我从它开始的进程在系统中“丢失”了吗?
    • 您启动的进程不会丢失,它会终止(即关闭)。因此,您有两个选择:为您要发送的每个命令运行“bconsole”并使用communicate - 这是最安全的方法,或者如果“bconsole”每次启动时间过长,以及 if 您确切知道您发送的每个命令会生成多少输出,您可以直接将命令写入标准输入并从标准输出/标准错误中读取预期的行数 - 但是,很容易死锁,您需要知道自己是什么在这种情况下做。
    • @adinanp:您可能希望pexpect 模块与子进程交互通信,就像在终端中一样。见Why not just use a pipe (popen())?
    【解决方案2】:

    感谢所有试图帮助我的人。 为了解决这个问题,我做了以下:

    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)
    

    我创建了一个方法“控制台”和我开始的班级的所有其他方法。

    这解决了我的问题。

    谢谢

    【讨论】:

      【解决方案3】:

      更好的方法是如下,

      任何子进程初始化都必须用try catch封装,以处理资源分配失败。成功则返回。

      通讯前先检查通道是否建立(无错误)再进行通讯。

      最好的方法是将“Popen”保持在您交流的任何地方。您最终可能会重复“Popen”两次。但这是安全的。

      “Popen”和“communicate”之间的任何未知中断都会使您的 python 作业永远挂起,需要手动终止。这当然是我们在现场不想要的

      【讨论】:

        猜你喜欢
        • 2015-07-20
        • 1970-01-01
        • 2016-08-26
        • 2013-09-27
        • 1970-01-01
        • 1970-01-01
        • 2016-07-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多