I am attempting to start the python interpreter by typing python into my terminal. I also want to pass some command line arguments. If I try python arg1 it things I am trying to open and run a script called arg1. So my question is, how can I pass command line arguments to python in the command line interpreter mode?
You already are.
Your arg1 is a command line argument - to the python interpreter.
Maybe you're thinking of a command line option? (which really is just a specific type of command line argument)
Using the -h argument (python -h) will print all such options.
python -Q new, for example, will launch the interpreter with the new float division by default.
On the other hand, if you want to pass command line arguments to your script, you need to specify them after the script name: python my_script.py arg1
If you are on a UNIX based system, you can also use a shebang on your script, which will allow you to simply execute your script by name, skipping python:
#!/usr/bin/env python
#your script here
then run ./my_script.py arg1
An easy way to do it is by using the subprocess module and input variables.
An example would be:
from subprocess import call
x = raw_input('Which command line arguments? ')
call(x, shell=True)
Try it with an ls command (dir for Windows users), it should work.
You can access the command line arguments using sys.argv
import sys
print sys.argv
% python scrpt.py a b c d
outputs: ['scrpt.py', 'a', 'b', 'c', 'd']
Use - to mark the end of python's interpreter options:
python --interpreter-option-1 --interpreter-option-2 - --my-custom-option option-value my-custom-argument
Related
This question already has an answer here:
terminal only running 2.7, even after changing alias
(1 answer)
Closed 1 year ago.
Thank you in advance for the feedback!
I have a simple hello.py file which I am exploring in the Command Line.
When I run the following command:
python hello.py
I get an expected output:
Hello World
But when I run it with the Execute Bit command
chmod +x hello.py
./hello.py
I get the following output:
('Hello', 'World')
I do not get why the second output is enclosed in parentheses and displayed as separately quoted strings. My python version is Python 3.8.5. If it matters my shell is zsh.
Here is the hello.py file:
import sys
# Define a main() function that prints a little greeting.
def main():
# Get the name from the command line, using 'World' as a fallback.
if len(sys.argv) >= 2:
name = sys.argv[1]
else:
name = 'World'
print ('Hello', name)
# This is the standard boilerplate that calls the main() function.
if __name__ == '__main__':
main()
For you to be able to run the script with just its name, the file needs to have a valid shebang line. You are not showing yours, but apparently your script has one, or else the shell would attempt to run it as a shell script. Unfortunately, your shebang is pointing to Python 2, where you would want it to point to Python 3.
On many Linux systems, #!/usr/bin/python (or the morally equivalent but somewhat more flexible #!/usr/bin/env python) will run Python 2, whereas #!/usr/bin/python3 (or #!/usr/bin/env python3) will run Python 3.
Whether python on the command line runs Python 3 is by and large irrelevant; this is probably an interactive alias set up by your shell, but it only works interactively.
This question already has answers here:
Actual meaning of 'shell=True' in subprocess
(7 answers)
Closed 8 months ago.
I would like to run a shell script from Python 3 in Linux passing two arguments that contain file paths to two different files. The shell script then calls a programme written in Python 2.
In Python 3, I call the shell script like this:
import os
import sys
os.chmod('/path/to/sh', 0o777)
subprocess.call(['/path/to/sh', '/path/to/file1', '/path/to/file2'], shell=True)
My shell script looks like this:
#!/bin/sh
set -x
path1=$1
path2=$2
python2 path/to/programme "$path1" "$path2"
Now, the file paths are empty, and the shell script returns something like python2 path/to/programme '' ''. Does someone know how I could correctly pass the file paths so that the programme written in Python 2 can read them?
Or is there even an easier solution such as using subprocess to directly call the programme written in Python 2?
There is no need for the shell script. You can use subprocess to run python2 directly.
a.py
#!/usr/bin/env python3
import subprocess
subprocess.call(['python2', './b.py', 'foo', 'bar'])
b.py
#!/usr/bin/env python2
import sys
print sys.argv
Running ./a.py outputs ['./b.py', 'foo', 'bar'].
You could also try using past.translation instead:
The past module provides an experimental translation package to help with importing and using old Python 2 modules in a Python 3 environment.
shell=True is only needed if you do something like
subprocess.run("/path/to/sh /path/to/file1 /path/to/file2", shell=True)
where the shell will split the single string into arguments that will identify as the program name and its arguments. But you already have the program name and its arguments identified, so
subprocess.run(['/path/to/sh', '/path/to/file1', '/path/to/file2'])
is all you need.
By using a list and shell=True, you are essentially asking Python to execute
sh -c /path/to/sh /path/to/file1 /path/to/file2
which uses /path/to/file1 to set the value of $0, not $1, in the command to execute.
I can run one program by typing: python enable_robot.py -e in the command line, but I want to run it from within another program.
In the other program, I imported subprocess and had subprocess.Popen(['enable_robot', 'baxter_tools/scripts/enable_robot.py','-e']), but I get an error message saying something about a callback.
If I comment out this line, the rest of my program works perfectly fine.
Any suggestions on how I could change this line to get my code to work or if I shouldn't be using subprocess at all?
If enable_robot.py requires user input, probably it wasn't meant to run from another python script. you might want to import it as a module: import enable_robot and run the functions you want to use from there.
If you want to stick to the subprocess, you can pass input with communicate:
p = subprocess.Popen(['enable_robot', 'baxter_tools/scripts/enable_robot.py','-e'])
p.communicate(input=b'whatever string\nnext line')
communicate documentation, example.
Your program enable_robot.py should meet the following requirements:
The first line is a path indicating what program is used to interpret
the script. In this case, it is the python path.
Your script should be executable
A very simple example. We have two python scripts: called.py and caller.py
Usage: caller.py will execute called.py using subprocess.Popen()
File /tmp/called.py
#!/usr/bin/python
print("OK")
File /tmp/caller.py
#!/usr/bin/python
import subprocess
proc = subprocess.Popen(['/tmp/called.py'])
Make both executable:
chmod +x /tmp/caller.py
chmod +x /tmp/called.py
caller.py output:
$ /tmp/caller.py
$ OK
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
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)
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)
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.)
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')
NOTE: Many of the same questions have been asked about python raw_input() in sublime text. This question is NOT about sublime. The python code is called in Windows command prompt which unlike the sublime terminal does support interactive inputs.
I have a python program that takes user input with the built-in function raw_input(). See below.
def password_score():
pwd = raw_input('Enter a password: ')
gname = raw_input('Enter your first name: ')
...
I call the program in cmd by
echo password_score()|python -i a06q1.py
where a06q1.py is the file name. The path of the python directory has been added to system variable %PATH% temporarily. I am in the directory of the file. My operating system is Windows 7. I am using python 2.6. The same command has worked until now.
Then cmd returns
File "<stdin>", line 1, in <module>
File "a06q1.py", line 27, in password_score
pwd = raw_input(p_prompt)
EOFError: EOF when reading a line
Is there a way to get around it within cmd?
EDIT: I just tried in on an iOS terminal too. With the same command as in cmd (with quotes), it returns the same error. Is there anything wrong about the command line I used? Thank you!
EDIT: Sebastian's answer solves the problem. The command should adapt to windows as follows.
printf "a06q1.password_score()\n'arg1\n'arg2"|python -i -c "import a06q1"
The single quotes succeeding \n can be replaced by spaces. They separate multiple inputs.
EOF means that there is no more input. And it is true, the only line is consumed by -i option:
$ echo "f()" | python -i -c "def f(): print('x'); input('y\n')"
>>> x
y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in f
EOFError: EOF when reading a line
>>>
Provide more input:
$ printf "f()\n'z'" | python -i -c "def f(): print('x'); print(input('y\n')*3)"
>>> x
y
zzz
>>>
As you said: it is "canonically bad" to specify a function to run in such manner. If you don't know in advance, what function you want to run then as an alternative, you could run it as:
$ python -c "from a06q1 import password_score as f; f()" < input_file.txt
What you're trying to do is not the way to call a specific function from the command line.
You need an if __name__ == "__main__"-block in your code.
At the end of your file:
`if __name__ == "__main__"`:
password_score()
And now run the program by:
python a06q1.py
If you run a python file from the command file, the __name__-variable will be "__main__". Notice that if you import a06q1 to some other python file, the name will equal the module name and thus the if __name__ block evaluates to False.
From python docs:
This module represents the (otherwise anonymous) scope in which the
interpreter’s main program executes — commands read either from
standard input, from a script file, or from an interactive prompt. It
is this environment in which the idiomatic “conditional script” stanza
is run
As J.F Sebastian writes in the comments, you can also execute a specific python command by providing the -c switch. The following will import the a06q1 and run function_name:
python -c "from a06q1 import function_name; function_name()"