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.
Related
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.
When I manually run this command in Terminal, it executes, but through Python it gives the error that the directory is not available in Python packages.
I am using the following command
source ~/trytry/shell.sh
This is my test shell file:
#!/bin/sh
echo hello
when I executed " source ~/test.sh ", it will print hello at console.
This is my python code:
>>> import commands
>>> commands.getstatusoutput("source ~/test.sh")
(0, 'hello')
It works without any problem. So, would you please show your code?
What it looks like to me is that you have a shell script, and not a python file which would have the .py extension instead of .sh. The error may have to do with the fact that it isn't a python file you're trying to run.
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')
I have a python script test.py I'm working on. I'd like to make edits and re-run it. I'm using Terminal on OSX to run the script. I can't get the script to run a second time without quitting out of terminal and starting it again.
# test.py
print "Howdy"
Terminal window:
$ python
>>> import test
Howdy
>>> import test
>>>
Question 1: How do I get the script to run again?
Question 2: Or is python designed to work like this:
# test.py
def printStuff():
print "Howdy"
Terminal:
$ python
>>> import test
>>> test.printStuff()
Howdy
>>> test.printStuff()
Howdy
>>>
1: you can use reload(moduleName) to do what you're trying to do (but see below).
2: There's a few different patterns, but I typically have a main() function inside all of my modules that have a clear "start point", or else I'll just have a bunch of library functions. So more or less what you're thinking in your example. You're not really supposed to "do stuff" on import, unless it's setting up the module. Think of a module as a library, not a script.
If you want to execute it as a script (in which case you shouldn't be using import), then there's a couple options. You can use a shebang at the top of your python script (Should I put #! (shebang) in Python scripts, and what form should it take?) and execute it directly from the command line, or you can use the __main__ module in your script as an entry point (https://docs.python.org/2/library/main.html), and then call the script with python from the command line, e.g. python myscript.
Use Python's reload() method:
https://docs.python.org/2/library/functions.html#reload
You want to use the reload method
>>> import test
Howdy
>>> reload(test)
Howdy
Am trying to run the following python program
import re
regex=re.compile("http...imgs.xkcd.com.comics.[\\S]*.[jpg|png]")
f=open('out.txt')
for a in f:
print regex.findall(a)
print '\n'
when I type the code into the interpreter manually, it works as expected
but when i save it as a file and try to run it , it gives errors.
The command i used to run it is
chmod +x
sudo ./pymod.py
ERROR:
./pymod.py: 2: Syntax error: "(" unexpected
if i dont use sudo, the error i get is
./pymod.py: line 2: syntax error near unexpected token `('
./pymod.py: line 2: `regex=re.compile("http...imgs.xkcd.com.comics.[\\S]*.[jpg|png]")'
am using ubuntu 10.04 with everything on default
it takes about 10-15 seconds for the error to appear
Your file should start with shebang. You should include the path to the python interpreter
#!/usr/bin/env python
import re
regex=re.compile("http...imgs.xkcd.com.comics.[\\S]*.[jpg|png]")
Check out : http://en.wikipedia.org/wiki/Shebang_(Unix)
This is probably executing as a bash script instead of in Python. Put
#!/usr/bin/env python
at the beginning of your script.
When you set something as executable, you have to specify what you want it to run it with, or Linux will consider it to be a bash script.
Add this as the first line of the file:
#!/usr/bin/python
Or run it like:
python pymod.py
Cheers!
Either use the "shebang". I.e. put
#! /usr/bin/python
as the first line of your script.
Or teach your ubuntu how to treat python scripts without it
as described here: http://www.daniweb.com/code/snippet241988.html