The right answer (using Python 2.7 and later, since check_output() was introduced then) is:
py2output = subprocess.check_output(['python','py2.py','-i', 'test.txt'])
To demonstrate, here are my two programs:
py2.py:
import sys
print sys.argv
py3.py:
import subprocess
py2output = subprocess.check_output(['python', 'py2.py', '-i', 'test.txt'])
print('py2 said:', py2output)
Running it:
$ python3 py3.py
py2 said: b"['py2.py', '-i', 'test.txt']\n"
Here's what's wrong with each of your versions:
py2output = subprocess.check_output([str('python py2.py '),'-i', 'test.txt'])
First, str('python py2.py') is exactly the same thing as 'python py2.py'—you're taking a str, and calling str to convert it to an str. This makes the code harder to read, longer, and even slower, without adding any benefit.
More seriously, python py2.py can't be a single argument, unless you're actually trying to run a program named, say, /usr/bin/python\ py2.py. Which you're not; you're trying to run, say, /usr/bin/python with first argument py2.py. So, you need to make them separate elements in the list.
Your second version fixes that, but you're missing the ' before test.txt'. This should give you a SyntaxError, probably saying EOL while scanning string literal.
Meanwhile, I'm not sure how you found documentation but couldn't find any examples with arguments. The very first example is:
>>> subprocess.check_output(["echo", "Hello World!"])
b'Hello World!\n'
That calls the "echo" command with an additional argument, "Hello World!".
Also:
-i is a positional argument for argparse, test.txt is what the -i is
I'm pretty sure -i is not a positional argument, but an optional argument. Otherwise, the second half of the sentence makes no sense.
The right answer (using Python 2.7 and later, since check_output() was introduced then) is:
py2output = subprocess.check_output(['python','py2.py','-i', 'test.txt'])
To demonstrate, here are my two programs:
py2.py:
import sys
print sys.argv
py3.py:
import subprocess
py2output = subprocess.check_output(['python', 'py2.py', '-i', 'test.txt'])
print('py2 said:', py2output)
Running it:
$ python3 py3.py
py2 said: b"['py2.py', '-i', 'test.txt']\n"
Here's what's wrong with each of your versions:
py2output = subprocess.check_output([str('python py2.py '),'-i', 'test.txt'])
First, str('python py2.py') is exactly the same thing as 'python py2.py'—you're taking a str, and calling str to convert it to an str. This makes the code harder to read, longer, and even slower, without adding any benefit.
More seriously, python py2.py can't be a single argument, unless you're actually trying to run a program named, say, /usr/bin/python\ py2.py. Which you're not; you're trying to run, say, /usr/bin/python with first argument py2.py. So, you need to make them separate elements in the list.
Your second version fixes that, but you're missing the ' before test.txt'. This should give you a SyntaxError, probably saying EOL while scanning string literal.
Meanwhile, I'm not sure how you found documentation but couldn't find any examples with arguments. The very first example is:
>>> subprocess.check_output(["echo", "Hello World!"])
b'Hello World!\n'
That calls the "echo" command with an additional argument, "Hello World!".
Also:
-i is a positional argument for argparse, test.txt is what the -i is
I'm pretty sure -i is not a positional argument, but an optional argument. Otherwise, the second half of the sentence makes no sense.
Since Python 3.5, subprocess.run is recommended instead of subprocess.check_output:
>>> subprocess.run(['cat','/tmp/text.txt'], check=True, stdout=subprocess.PIPE).stdout
b'First line\nSecond line\n'
Since Python 3.7, instead of the above, you can use capture_output=True parameter to capture stdout and stderr:
>>> subprocess.run(['cat','/tmp/text.txt'], check=True, capture_output=True).stdout
b'First line\nSecond line\n'
Also, you may want to use universal_newlines=True or its equivalent since Python 3.7 text=True to work with text instead of binary:
>>> stdout = subprocess.run(['cat', '/tmp/text.txt'], check=True, capture_output=True, text=True).stdout
>>> print(stdout)
First line
Second line
Videos
I'm not getting an error but its not really printed what i wanted
I was trying to get these echo commands to show in either idle or running .py script
import subprocess allscripts = ["./scripty1", "./scripty2", "./scripty3", "./scripty4", "./scripty5"] for x in allscripts: subprocess.run([x], shell=True, capture_output=True) print(subprocess.check_output)
All it prints is this though
λ /bin/python /mnt/Stor2/Media/Share/DevShare/Py/InstallScript/InstallScript.py<function check_output at 0x7f7f2a94c040><function check_output at 0x7f7f2a94c040><function check_output at 0x7f7f2a94c040><function check_output at 0x7f7f2a94c040><function check_output at 0x7f7f2a94c040>
You can get the error code and results from the exception that is raised.
This can be done through the fields returncode and output.
For example:
import subprocess
try:
grepOut = subprocess.check_output("grep " + "test" + " tmp", shell=True)
except subprocess.CalledProcessError as grepexc:
print("error code", grepexc.returncode, grepexc.output)
Python 3.5 introduced the subprocess.run() method. The signature looks like:
subprocess.run(
args,
*,
stdin=None,
input=None,
stdout=None,
stderr=None,
shell=False,
timeout=None,
check=False
)
The returned result is a subprocess.CompletedProcess. In 3.5, you can access the args, returncode, stdout, and stderr from the executed process.
Example:
>>> result = subprocess.run(['ls', '/tmp'], stdout=subprocess.DEVNULL)
>>> result.returncode
0
>>> result = subprocess.run(['ls', '/nonexistent'], stderr=subprocess.DEVNULL)
>>> result.returncode
2
If you have Python version 2.7 or later, you can use subprocess.check_output which basically does exactly what you want (it returns standard output as a string).
A simple example (Linux version; see the note):
import subprocess
print subprocess.check_output(["ping", "-c", "1", "8.8.8.8"])
Note that the ping command is using the Linux notation (-c for count). If you try this on Windows, remember to change it to -n for the same result.
As commented below, you can find a more detailed explanation in this other answer.
Output from subprocess.call() should only be redirected to files.
You should use subprocess.Popen() instead. Then you can pass subprocess.PIPE for the stderr, stdout, and/or stdin parameters and read from the pipes by using the communicate() method:
from subprocess import Popen, PIPE
p = Popen(['program', 'arg1'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = p.communicate(b"input data that is passed to subprocess' stdin")
rc = p.returncode
The reasoning is that the file-like object used by subprocess.call() must have a real file descriptor, and thus implement the fileno() method. Just using any file-like object won't do the trick.
See here for more info.