Reputation: 2040
I would like to create a file that will be used as standard input for a python script, and invoke said script with subprocess.call.
When I do it directly in the command line it works fine:
The input file:
# test_input
1/2/3
The python script
# script.py
thisDate = input('Please enter date: ').rstrip()
The following command works just fine:
python script.py < test_input
But when I try to do the following from within another python script, it doesn't work. (from this)
outfile1 = open('test_input', 'w')
outfile1.write('1/2/3')
outfile1.close()
input1 = open('test_input')
subprocess.call(['python', 'script.py'], stdin=input1)
But then I get the following error:
>>>thisDate = input('Please enter date: ').rstrip()
>>>AttributeError: 'int' object has no attribute 'rstrip'
When I did some debugging, it seems that it is getting the integer 0 as the input.
What is causing the inconsistency here? Are the two methods not equivalent (evidently they are not, but why)? My ultimate goal is to perform the exact same task as the above command line version that worked.
Thank you
Upvotes: 1
Views: 91
Reputation: 414265
python script.py < test_input
command should fail. You might mean: python3 script.py < test_input
instead due to the difference between input()
vs raw_input()
on Python 2 as mentioned in other answers. python
as a rule refers to Python 2 version.
if the parent script is run only using python3
then you could use sys.executable
to run the child script using the same python
version (the same executable):
#!/usr/bin/env python3
import subprocess
import sys
with open('test_input', 'rb', 0) as input_file:
subprocess.check_call([sys.executable or 'python3', 'script.py'],
stdin=input_file)
If the parent and the child may use different python versions then set the correct shebang in script.py
e.g., #!/usr/bin/env python3
and run the script directly:
#!/usr/bin/env python
import subprocess
with open('test_input', 'rb', 0) as input_file:
subprocess.check_call(['./script.py'], stdin=input_file)
Here, the child script may choose its own python version. Make sure the script has executable permissions: chmod +x script.py
. Note: Python Launcher for Windows understands the shebang syntax too.
Unrelated: use .communicate()
instead of outfile1.write('1/2/3')
:
#!/usr/bin/env python3
from subprocess import Popen, PIPE
with Popen(['./script.py'], stdin=PIPE, universal_newlines=True) as p:
p.communicate('1/2/3')
Upvotes: 0
Reputation: 180411
You are using input
when it should be raw_input
, input
in python2 will eval
the string. If you run the script with python3
it will work as is, for python2
change to raw_input
.
Using check_call
is usually a better approach and using with
to open your files.
import subprocess
with open('test_input') as input1:
subprocess.check_call(['python3', 'script.py'], stdin=input1)
Upvotes: 1
Reputation: 189417
In the first instance, the file has two lines, and input()
reads and parses the first line, which is a comment.
In the second case, the comment line is missing, so Python reads and parses a number.
You probably meant to use raw_input()
, or run the script with Python 3.
(You probably also meant for the input file to end with a newline, and it doesn't really make sense to use subprocess.call()
to run Python when you are already running Python.)
Upvotes: 0
Reputation: 2040
So chepner was correct. When I amended the following line:
subprocess.call(['python', 'script.py'], stdin=input1)
to:
subprocess.call(['python3', 'script.py'], stdin=input1)
it worked just fine.
(I am trying to do this in python3)
Upvotes: 0