Sylvain Berger
Sylvain Berger

Reputation: 117

Communicate with python subprocess while it is running

I running a subprocess that run a software in "command" mode. (This software is Nuke by The Foundy, in case you know that software)

When in command mode, this software is waiting for user input. This mode allow to create compositing scripts without any UI.

I have done this bit of code that start the process, find when the application is done starting then I try to send the process some commands, but the stdin doesn't seem to be sending the commands properly.

Here the sample code I did to test this process.

import subprocess

appPath = '/Applications/Nuke6.3v3/Nuke6.3v3.app/Nuke6.3v3' readyForCommand = False

commandAndArgs = [appPath, '-V', '-t'] 
commandAndArgs = ' '.join(commandAndArgs) 
process = subprocess.Popen(commandAndArgs, 
                           stdin=subprocess.PIPE, 
                           stdout=subprocess.PIPE, 
                           stderr=subprocess.STDOUT, 
                           shell=True, )

while True:
    if readyForCommand:
        print 'trying to send command to nuke...'
        process.stdin.write('import nuke')
        process.stdin.write('print nuke')
        process.stdin.write('quit()')
        print 'done sending commands'
        readyForCommand = False
    else:
        print 'Reading stdout ...'
        outLine = process.stdout.readline().rstrip()
        if outLine:
            print 'stdout:', outLine

            if outLine.endswith('getenv.tcl'):
                print 'setting ready for command'
                readyForCommand = True

    if outLine == '' and process.poll() != None:
        print 'in break!'
        break

print('return code: %d' % process.returncode) 

when I run nuke in a shell and send the same commands here is what I get:

sylvain.berger core/$ nuke -V -t
[...]
Loading /Applications/Nuke6.3v3/Nuke6.3v3.app/Contents/MacOS/plugins/getenv.tcl
>>> import nuke
>>> print nuke
<module 'nuke' from '/Applications/Nuke6.3v3/Nuke6.3v3.app/Contents/MacOS/plugins/nuke/__init__.pyc'>
>>> quit()
sylvain.berger core/$ 

Any idea why the stdin is not sending the commands properly? Thanks

Upvotes: 3

Views: 6108

Answers (2)

torek
torek

Reputation: 489818

The subprocess module is not intended for interactive communication with a process. At best, you can give it a single pre-computed standard input string and then read its stdout and stderr:

p = Popen(..., stdin=PIPE, stdout=PIPE, stderr=PIPE)
out, err = p.communicate(predefined_stdin)

If you actually need interaction, consider using pexpect.

Upvotes: 0

tobyodavies
tobyodavies

Reputation: 28099

your code will send the text

import nukeprint nukequit()

with no newline, thus the python instance will not try to execute anything, everything is just sitting in a buffer waiting for a newline

Upvotes: 3

Related Questions