Reputation: 2692
I'm very new to python and its subprocess module, but I'm trying to figure out how to get a command to run within a subprocess. Specifically, I'm running Magic Set Editor 2 in raw commandline interface mode (http://magicseteditor.sourceforge.net/doc/cli/cli) and I want a script that can take that and export a bunch of images from it. Doing this in cmd.exe through the interactive CLI is trivial:
mse --cli setName.mse-set
//entered the interactive CLI now.
> write_image_file(file:set.cards[cardNumber].name+".png", set.cards[cardNumber]
and that writes a png to my folder, so far so good. I can pull off the same thing with the raw commandline:
mse --cli setName.mse-set --raw
//entered the raw CLI now.
write_image_file(file:set.cards[cardNumber].name+".png", set.cards[cardNumber]
again, achieves a png and all that. Now the trick is, how do I get a python script to do the same thing? My current script looks like:
import subprocess
s = subprocess.Popen("mse --cli setName.mse-set --raw",shell=True)
s.communicate("write_image_file(file:set.cards[1].name+'.png',set.cards[1]")
I have shell=True because in cmd.exe it seems to open a new shell, but when I run this script it simply opens that shell and doesn't seem to run the second line, it sits there waiting for my input, which I want the script to provide.
I found an alternate method but it still doesn't quite click for me:
from subprocess import Popen, PIPE
s = Popen("mse --cli setName.mse-set --raw",stdin=PIPE)
s.communicate("write_image_file(file:set.cards[1].name+'.png',set.cards[1]")
...because I get the errors:
Traceback (most recent call last):
File "cardMaker.py", line 6, in <module>
s.communicate("write_image_file(file:set.cards[1].name+'.png',set.cards[1]")
File "C:\Python34\lib\subprocess.py", line 941, in communicate
self.stdin.write(input)
TypeError: 'str' does not support the buffer interface
edit: After solving the initial problem, I have another question; how do I send it multiple commands? Another s.communicate
line with the same command failed with the error: Cannot send input after starting communication
.
Upvotes: 0
Views: 2178
Reputation: 90869
From the documentation of subprocess
-
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. The optional input argument should be data to be sent to the child process, or None, if no data should be sent to the child. The type of input must be bytes or, if universal_newlines was True, a string.
(Emphasis mine)
You need to send in a byte-string as input to the communicate()
method , Example -
from subprocess import Popen, PIPE
s = Popen("mse --cli setName.mse-set --raw",stdin=PIPE)
s.communicate(b"write_image_file(file:set.cards[1].name+'.png',set.cards[1]")
Also , you should send the command to run as a list , Example -
from subprocess import Popen, PIPE
s = Popen(['mse', '--cli', 'setName.mse-set', '--raw'],stdin=PIPE)
s.communicate(b"write_image_file(file:set.cards[1].name+'.png',set.cards[1]")
Upvotes: 2