Reputation: 2323
The title to this may be confusing, but basically I want to be able to do the following:
import subprocess
subprocess.call(["python"])
subprocess.call(["import", "antigravity"])
subprocess.check_call(["print","\"This is so meta\" "])
subprocess.call(["exit()"])
Expected behavior would be that it would open up a python terminal session, then open up xkcd comic 353, print 'this is so meta' to the command line, and finally exit the python command line.
Basically, I want to be able to open a python session, and run commands in it from my python script. I also want to be able to check the output of commands I run in the script. Is this possible? and if so, what library do I need to be using? Will subprocess do this?
Upvotes: 6
Views: 371
Reputation: 879093
You could also use the code module:
import code
console = code.InteractiveConsole()
console.push('import antigravity')
console.push('print "something"')
If for some reason you wish to run this in a subprocess, then you could use the multiprocessing module:
import code
import multiprocessing as mp
def work():
console = code.InteractiveConsole()
console.push('import antigravity')
console.push('print "something"')
if __name__ == '__main__':
proc = mp.Process(target=work)
proc.start()
proc.join()
To redirect stdout to a variable:
import code
import sys
class MyStream(object):
def __init__(self, target):
self.target = target
self.value = None
def write(self, s):
if s.strip():
self.value = s
sys.stdout = stream = MyStream(sys.stdout)
console = code.InteractiveConsole(locals=locals())
console.push('import antigravity')
console.push('print "something"')
sys.__stdout__.write('output: {}\n'.format(stream.value))
prints
output: something
Note that the console
's sys.stdout
has been redirected to MyStream(sys.stdout)
. It prints nothing, but stores the last string in self.value
. To print to the string you could use sys.__stdout__.write
(note the underscores).
Upvotes: 2
Reputation: 9070
If you need to communicate with process you should use communicate()
method instead stdin.write()
otherwise you can find some no desirable effects.
Warning Use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process.
Source: http://docs.python.org/2/library/subprocess.html#popen-objects
from subprocess import PIPE, STDOUT, Popen
e = Popen(["/usr/local/bin/python3"], stdout = PIPE, stdin = PIPE, stderr = STDOUT, shell = False)
out, err = e.communicate(b"""
import sys
print('Interactive python version: %s' % str(sys.version))
sys.exit(4)
""")
e.wait()
print ('Exit code', e.returncode)
print ('Output', out)
Upvotes: 2
Reputation: 26756
Something like this...
import subprocess
proc = subprocess.Popen(
'python',stdout=subprocess.PIPE,
stdin=subprocess.PIPE)
proc.stdin.write('import antigravity\n')
proc.stdin.write('print "something"\n')
proc.stdin.close()
result = proc.stdout.read()
print result
So we're creating a process and telling it that input will come from stdin (like someone typing). We then write anything we like to that and read the response from stdout (what would normally be printed to the screen)
Upvotes: 3