This question already has answers here:
Cannot pass an argument to python with "#!/usr/bin/env python"
(9 answers)
Closed 9 years ago.
I have this non-portable shebang:
#!/usr/bin/env python -u
It is non portable because python -u is fed as one single arg to env on my system.
Challenge: make this shebang portable changing the shebang only - that is to say a one-liner.
In other words, no solutions
from the question Disable output buffering
from the question Cannot pass an argument to python with "#!/usr/bin/env python"
I'd use the following:
#!/bin/sh
"""true"
exec python -u "$0" "$#"
"""
# python code goes here
The line """true" will be parsed by sh as true, because it consists of an empty "" string followed by "true". Since true is a no-op command, it will be effectively ignored, and the following line will execute the Python interpreter.
On the other hand, Python will parse the """true" line very differently, as the opening of a triple-quoted string which starts with true" and is closed two lines below. Since the string is not used for anything, the Python interpreter will effectively ignore the shell snippet that starts up Python. It is the difference in interpretation of """xxx" that allows Python and sh code coexist in the same script.
For a simple test, append something like:
import sys
print "hello!", sys.argv
Given a reasonable sh implementation (and taking into account the time to start Python), this should not be measurably slower than using env.
Related
This question already has answers here:
How to make a call to an executable from Python script?
(3 answers)
Closed 5 years ago.
I have a command like that spins off some calculations and stores some output in a folder. So, I have this command that works on the bash command (in Ubuntu).
/home/usr2/AXE/prog1.exe -k 1 -m /home/usr2/AXE/config.txt
However, I would like to "call" this from inside a python program.
The final idea is to generate lots of serial processes of this nature inside python.
/home/usr2/AXE/prog1.exe -k 1 -m /home/usr2/AXE/config.txt
/home/usr2/AXE/prog1.exe -k 2 -m /home/usr2/AXE/config.txt
/home/usr2/AXE/prog1.exe -k 3 -m /home/usr2/AXE/config.txt
...
...
/home/usr2/AXE/prog1.exe -k 2000 -m /home/usr2/AXE/config.txt
SO FAR
import os
os.system('"/home/usr2/AXE/prog1.exe -k 1 -m /home/usr2/AXE/config.txt"')
This gives me command line output of Out[11]: 32512, but the output file is not produced in the requisite folder.
What am I doing wrong?
P.S. No idea about Bash programming. But would be interested in Bash solutions as well.
The immediate problem seems to be an excess of quotation marks. os.system takes a string containing the command you want to execute. So to execute the shell command echo hello, you would call os.system('echo hello') from Python. Calling os.system('"echo hello"') tries to execute the shell command "echo hello"; in other words, it looks for a single executable file in your PATH named echo hello, which presumably doesn't exist and certainly isn't what you want. So get rid of one set of quotes. Either one is fine since Python treats single and double quotes the same.
You can also try replacing your use of os.system with subprocess.run, also from the standard library. Instead of a single string containing the command, you pass it a sequence of strings, each of which is one token from the shell command you'd like to run. So in our example you could do subprocess.run(('echo', 'hello')). The os.system function is more or less deprecated in favor of subprocess.run.
This question already has an answer here:
! in a string makes it unusable in a command line - error message "event not found" [duplicate]
(1 answer)
Closed 5 years ago.
I got this strange error message trying to write shebang to a python script:
$ echo "#!/usr/bin/env python" > scripts/sandbox.py
-bash: !/usr/bin/env: event not found
$ echo "say what?" > scripts/sandbox.py
Immediately doing the same thing but without using shebang line works. What is this behavior and how can it be overcome?
! is a special character to bash, it is used to refer to previous commands. It is expanded within double-quotes.
To avoid that, enclose them in single-quotes instead:
echo '#!/usr/bin/env python' > scripts/sandbox.py
#mklement0 clarified it beautifully in a comment:
More specifically, ! is special to Bash's history expansion feature, which is on by default (only) in interactive shells. In addition to avoiding it by using single-quoted strings, it can be turned off altogether with set +H
This question already has answers here:
What is the Python equivalent of `set -x` in shell?
(4 answers)
Closed 5 years ago.
I'd like to run my python script in such a way that every line is printed as it is executed (for debugging purposes), like how you can add set -x to a bash script. Is this possible? If not, what other strategies are there for debugging python that don't involve adding log lines everywhere? I usually use pdb but this isn't always suitable for time sensitive applications eg networking.
Use the trace module.
$ python -m trace -t myscript.py | grep myscript.py
This question already has answers here:
How to avoid .pyc files?
(10 answers)
Closed 9 years ago.
Is there a way to stop python from creating .pyc files, already in the shebang (or magic number if you will) of the Python script?
Not working:
#!/usr/bin/env python -B
it is possible by putting your python interperter path directly in the she bang instead of using env.
#!/usr/bin/python -B
of course this means you lose out on some of the portability benefits of using env. There is a discussion of this issue with env on the wikipedia Shebang page. They use python as one of their env examples.
According to the man page for env, you can pass name=value to set environment variables. The PYTHONDONTWRITEBYTECODE environment variable causes Python to not write .py[co] files (the same as the -B flag to python). So using
#!/usr/bin/env PYTHONDONTWRITEBYTECODE=1 python
should do the trick.
EDIT:
I tested this with a simple Python script:
#!/usr/bin/env PYTHONDONTWRITEBYTECODE=1 python
print 1
then
$chmod +x test.py
$./test.py
1
$ls
test.py
(but not test.pyc)
Yes, if and only if, we assume the Python program runs in a somewhat POSIX compatible system (for /bin/sh), this will work:
(IMPROVED based on input from glglgl)
#!/bin/sh
"exec" "python" "-B" "$0" "$#"
# The rest of the Python program follows below:
Alas, no. The shebang stuff is limited to giving an executable and one parameter.
So env tries to execute python -B with the given file as one argument instead of python with -B and the current file as two arguments.
I don't see a way to achieve the wanted goal.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Python equivalent to perl -pe?
Is there a way to process each line of stdin with a given Python command without setting up things with boilerplate code?
With Perl, I can just do something like:
perl -pe '... command ...'
can I do the same with Python?
Note: something similar is possible with many other tools, e.g. sed, awk, etc...
Python is not as convenient as Perl in this regard, but you can get close to Perl's -p flag using fileinput, like this:
python -c 'for ln in __import__("fileinput").input(): print ln.rstrip()' files...
This will automatically open files in sequence like Perl does, or use the standard input if no files are provided. Replace print with any kind of processing. You might need multiple lines to do anything useful, but that is not a problem for most shells.
Note that rstrip is needed to avoid duplication of newlines from the source lines and those added by the print statement. If you're not printing the line, you don't need to call it.
Try -c interpreter option:
python -c "print 'cool'"