adinanp
adinanp

Reputation: 935

Python - subprocess I/O operation on closed file

I have tried with the class below, execute commands in sequence with subporcess module in python2.6.

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)

However, if I try the following code, I get the error: ValueError: I / O operation on closed file

from pconsole import BaculaActions

myconsole = BaculaActions()

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

Anyone have idea what can be wrong? I thank

Upvotes: 2

Views: 22674

Answers (3)

Haroon Rashedu
Haroon Rashedu

Reputation: 155

Better way is to do as below,

Any sub process initialization must be encapsulated with try catch, to handle resource allocation failures. Then return it, if success.

Before communicating, check whether channel is established (no errors) then communicate.

Best way is to keep "Popen" on the same place whereever you communicate.You may end up duplicating "Popen" two times. But this is safe.

Any unknown interrupts between “Popen” and “communicate”, will make your python job as hanging forever and will need manual kill. This is certainly what we don’t want in live

Upvotes: -2

adinanp
adinanp

Reputation: 935

Thanks to everyone who somehow tried to help me. As a solution to the problem, I made the following:

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)

I created a method "console" and all other methods of my class I start.

This solved my problem.

Thank you

Upvotes: 1

isedev
isedev

Reputation: 19601

The manual says it all really:

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.

After you run the first command and get the result, the 'bconsole' process has terminated, the pipes are closed and hence the error on the second communicate call.

Upvotes: 6

Related Questions