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
Related
This question already has answers here:
Environment variables set from python not visible in shell script
(2 answers)
Closed 7 months ago.
I defined a shell script with a python script inside on the fly. Getting variables from shell to Python works fine, but the other way round does not work as expected. My Idea was to create an env variable os.environ["NEW_VAR"] = "test", but when trying is echo it, it is just None.
#!/bin/bash
args=("$#")
GIT_PASSWORD=${args[0]}
export GIT_PASSWORD=$GIT_PASSWORD
python - << EOF
import os
print(os.environ.get("GIT_PASSWORD"))
os.environ["NEW_VAR"] = "test"
EOF
echo $GIT_PASSWORD
echo $NEW_VAR
echo "Back to bash"
Why does that not work and 2. What is the correct way to pass a variable here?
Thank you!
Written in the comments, inheriting environment variables only works from parent to child processes, not the other way round.
if you need shell variables set from a python script you can create the output in your shell script and eval the results:
eval "$(python -c 'print("HELLO=WORLD")')"
echo "$HELLO"
yields WORLD
I stumble over a strange behavior of a #!/bin/bash script.
I got the variable SD=/SOME_VALID_PATH and SCRIPT=SOME_PYTHON_SCRIPT.py. What I want to do now in my script is eval python ${SD}/${SCRIPT}.
What happens is that the result looks like python /SOME_VALID_PATH/ SOME_PYTHON_SCRIPT.py. Note the space between the path and the script's name, so naturally, this command is not executed.
echo ${SD} gives /SOME_VALID_PATH and echo ${SCRIPT} gives SOME_PYTHON_SCRIPT.py, no spaces whatsoever.
Any ideas what I (generally) might do wrong?
I am not really sure why you're trying to use eval the way you mentioned (as mentioned in the comments a sample of your code will be helpful). It is likely the error you mentioned is because eval concatenates the string provided as its argument and it is your responsibility to make sure that the command syntax is correct. So it may be that python is getting the path (SD) and SCRIPT as two different arguments (separated by space) and so it fails to execute the path which is probably a directory.
You can use command substitution with eval and echo for example to make sure that the strings are properly represented. An example is given below where I have defined two variables for path and script name. The script name contains a space so a normal eval will throw an error.
$ echo $var1
/home/user/Documents/Temp
$ echo $var2
temp.py
$ echo \"$var1/$var2\"
"/home/user/Documents/Temp/ temp.py"
$ cat "$(echo $var1/$var2)"
print "Hello World"
$ eval python $var1/$var2
/home/user/bin/python: can't find '__main__' module in '/home/user/Documents/Temp/'
$ eval python $(echo \"$var1/$var2\")
Hello World
But this is probably not the best way to do things. Spaces should be avoided in paths.
This question already has answers here:
What does the $ mean when running commands?
(5 answers)
Closed 7 years ago.
As a beginner in Python, I'm reading a book written by Bill Lubanovic
I found something weird.
In that book, After saving simple code in test1.py, which is
print("This standalone program works!")
it says python can run it by typing in
$ python test1.py
However, whenever I try to use that, syntax error happens.
Although I know there are other methods like using exec() which I found in this website, I wanna know why book uses that method which doesn't work at least for me.
It means you need to type everything but the $ in the terminal.
python test1.py
It's just a convention though. Authors also use > python test1.py and other notations.
I don't know which version of his book you're reading, but he mentions it in this version.
In the example that follows, $ is a sample system prompt for you to type a command like python in the terminal window. We’ll use it for the code examples in this book, although your prompt might be different.
You are not supposed to enter the $.
The $ represents the shell/terminal prompt. This is the string of characters that appear in your terminal when it is waiting for input, although $ typically indicates some flavour of unix, e.g. linux.
Your terminal will probably use a different prompt, e.g.
[user#localhost ~]$
Or, if you are using a Windows terminal you might see :
C:\>
or
C:\WINDOWS>
Question was answered in following stackoverflow post:
What does the $ mean when running commands?
What does the $ mean when running commands?
As of now, Python does not implement $ in its syntax. So, it has nothing to do with Python.
Instead, what you are seeing is the terminal prompt of a Unix-based system (Mac, Linux, etc.)
So basically is terminal prompt and you should type in only: python test1.py without $ sign. another example is ~ when using oh-my-zsh.
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.
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'"