I want write a shell script that will run a Python Code stored in a shell variable $CODE.
#!/bin/bash
python3 $CODE
But this does not work, is there any way to do this? Any help is appreciated.The program that will be run:
print("Hello World")
export CODE='print("Hello World")'
Use the -c option.
python3 -c "$CODE"
python3 <<< "$CODE"
[Python.Docs]: Command line and environment - -c <command> states:
Execute the Python code in command. command can be one or more statements separated by newlines, with significant leading whitespace as in normal module code.
Example:
[064bit prompt]> CODE='import sys;print("Hello World");print(sys.version)'
[064bit prompt]> python -c "${CODE}"
Hello World
3.8.10 (default, Jun 22 2022, 20:18:18)
[GCC 9.4.0]
But this comes with some limitations. I'd save the code in a script and run that instead.
Related
By loading JSON from stdin before starting the REPL, I can pipe JSON outputs from other commands and work with the JSON data in Python.
I've tried something like and it worked:
kubectl get po -o json | cp /dev/stdin /tmp/data.json && python -i -c "import json; data = json.load(open('/tmp/data.json'))" && rm /tmp/data.json
Now I want to make it a script, so I write the following script:
#!/bin/bash -i
tmp_file=$(mktemp /tmp/ipyjson.XXXXXX)
cp /dev/stdin $tmp_file
python -i -c "import json; data = json.load(open('$tmp_file')); print(data)"
rm $tmp_file
And change the previous command to kubectl get po -o json | new_script.
But this time the REPL quits immediately after starting up, I have no idea what's the difference here. Maybe something about the interactive mode?
Edit:
I've also tried reading sys.stdin directly and met the same issue:
❯ k get po -o json | ipython -i -c "import sys, json; data = json.load(sys.stdin)"
Python 3.10.2 (main, Feb 11 2022, 14:13:20) [Clang 13.0.0 (clang-1300.0.29.30)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: Do you really want to exit ([y]/n)?
As you can see, ipython quited immediately with the prompt "Do you really want to exit ([y]/n)?".
I want to check whether python 3 is installed on my Ubuntu. I'm using this script:
#!/usr/bin/env sh
#install firefox if does not exist
if ! command -v python3 >/dev/null 2>&1
then
echo "not installed"
else
echo "installed"
fi
When I run this script, the output is installed, but when I check my python using python --version, I get this output:
Python 2.7.17
Which, as far as I know, means that the latest version of python on my Ubuntu is 2.7 not 3.x. What's wrong?
The output of command -v python3; echo $?:
/usr/bin/python3
0
The output of ls -l /usr/bin/python3:
lrwxrwxrwx 1 root root 9 Nov 14 09:13 /usr/bin/python3 -> python3.7
The output of ls -l /usr/bin/python3.7:
-rwxr-xr-x 2 root root 5102632 Oct 27 11:43 /usr/bin/python3.7
The output of which python:
/usr/bin/python
The output of ls -l /usr/bin/python:
lrwxrwxrwx 1 root root 7 Jan 19 08:04 /usr/bin/python -> python2
The output of ls -l /usr/bin/python2:
lrwxrwxrwx 1 root root 9 Jan 19 08:04 /usr/bin/python2 -> python2.7
Also I have another Ubuntu on a separate VM, the output of python --version, returns command 'python' not found, but when I execute the above commands for this VM as well, it returns similar responses (indicating that python is installed).
https://www.python.org/dev/peps/pep-0394/
Note: You can have an environment where you have both Python 2 and Python 3 installed, and python can point to either. (Most likely python2 for backward compatibility purpose.) Python 3 applications should always use the python3 command and not python.
Try the whereis command. It will tell you where python3 is.
whereis python
Or better yet
whereis python3
The output should be a path, or a list of paths. You might see something like:
python3: /usr/bin/python3.6m /usr/bin/python3.6 /usr/bin/python3.6m-config
/usr/bin/python3 /usr/bin/python3.6-config /usr/lib/python3.6 /usr/lib/python3
/usr/lib/python3.7 /usr/lib/python3.8 /etc/python3.6 /etc/python3 /usr/local
Then make sure your PATH variable has at least one of the directories above within it. The PATH environment variable is essentially a list of directories that contain executables (programs). When you type something on your command line your terminal program will search the directories listed in PATH for the executable you specified.
echo $PATH
/home/USER/.pyenv/shims:/home/USER/.pyenv/bin:/home/USER/esp/xtensa-esp32-
elf/bin:/home/USER/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:
/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
You might have a directory in your PATH that is messing things up, or you might need to add a new directory.
Because so many programs have been written using Python 2, many operating systems keep Python 2 in their repository, and this isn't going to change any time soon.
So when you installed Python, it added Python 2 to /usr/bin/ (maybe /usr/bin/python2, maybe /usr/bin/python2.7, etc.), and pointed /usr/bin/python to the same location. When you installed Python 3 it also installed Python 3, to /usr/bin/python3.
When you test whether python3 is installed, you find that it is. According to PEP 394, /usr/bin/python should refer to Python 2. Ubuntu documentation explains what that means and what it doesn't:
What this does not mean:
/usr/bin/python will point to Python 3. No, this is not going to happen (unless PEP 394 advocates otherwise, which is doubtful for the foreseeable future). /usr/bin/python and /usr/bin/python2 will point to Python 2.7 and /usr/bin/python3 will point to the latest supported Python 3 version.
Python 2 will be removed from the archive. No, this is not going to happen. We expect Python 2.7 to remain supported and available in Ubuntu for quite a long time, given that PEP 373 promises upstream bug fix maintenance support until 2020. It would be nice if we could demote Python 2 to universe, but that's currently problematic for technical reasons relating to multi-Python version support in Debian/Ubuntu.
Basically, while all development should be geared toward Python 3, the python command (/usr/bin/python) should point to Python 2 in order to keep current programs from breaking.
If you'd like to access Python 3, it's recommended that you call python3. (You could also rebind /usr/bin/python to point to python3, but this is highly unrecommended. A more useful solution to most users would be to create an alias to python3.)
Short version: Your script works. Python 3 is installed. If you want the terminal to open Python 3 when you type python, add an alias alias python=python3.
I have a python script abc.py. Inside a shell script file, I call it ./abc.py
Inside abc.py, at the top, I have #!/usr/bin/python
test -x abc.py && echo true || echo false return true
On executing the shell script, it says ./abc.py: Command not found.
It works if I call it as python ./abc.py instead of just ./abc.py
The issue is only with this abc.py file that I created today. The older python scripts in the same directory with different purpose and names work without any issue.
I have referred the correct path of the file BTW. What could be the issue?
In tcsh, this happens when the interpreter is invalid:
$ cat foo
#!/invalid
$ tcsh -c './foo'
./foo: Command not found.
$ bash -c './foo'
bash: ./foo: /invalid: bad interpreter: No such file or directory
This could be for several reasons. Perhaps your path is wrong for your system:
% type python
python is /usr/local/bin/python
in this case the script needs to start with #!/usr/local/bin/python instead.
Alternatively, the script could have Windows line endings (carriage returns):
$ cat -v foo
#!/usr/bin/python^M
...^M
In this case, save it with Unix line endings instead.
Trying to replicate your setup as follows:
File: asdf.py
#!/usr/bin/python
print("Hello World")
File: asdf.sh
#!/bin/bash
if [ -x asdf.py ]; then ./asdf.py ; else echo "Arrrrgh. File does not exist or does not have executable permisions"; fi
Now I save the files in the same directory, e.g. the Desktop, make them executable and run the shell script from the terminal.
usr#cmptr $ chmod +x asdf.{py,sh}
usr#cmptr $ ls -la asdf.{py,sh}
-rwxr-xr-x 1 usr usr 613 Mar 15 22:22 asdf.py
-rwxr-xr-x 1 usr usr 56 Mar 15 22:14 asdf.sh
usr#cmptr $ ./asdf.sh
Hello World
Now, maybe I have misunderstood your setup but this should work just fine.
This question already has answers here:
Detect python version in shell script
(18 answers)
Closed 4 years ago.
I was trying to write a bash script to test the python version. However, I found python --version behave weirdly for python 2, as I can't process its output using any tool. I have tested the same script on Mac OS (10.13.5) and AWS Linux (GUN/Linux #1 SMP Fri Feb 16 00:18:48 UTC 2018). So I think the problem is related to python 2.
The script and corresponding output are:
$ echo $(python --version) | awk '{print $2}'
> Python 2.7.10
But the output should be 2.7.10.
$ echo $(python --version) > weird.txt
> Python 2.7.10
$ cat weird.txt
>
So the output cannot be written into a file as well.
The same script to test for python3 has a totally different result
$ echo $(python3 --version) | awk '{print $2}'
> 3.6.5
But python3's output can be written into a file.
$ echo $(python3 --version) > weird.txt
$ cat weird.txt
> Python 3.6.5
I have found the reason for this difference is that python --version does not output a normal string or whatsoever. Maybe it calls another command to output the result for it??? Thus the result cannot be caught by current process?? (just pure guess here)
Can anyone help me to figure out why there is the difference here? There are probably of million ways to test for python version. But I'm just super curious about what is happening here.
Thanks for all the replies. Just found a useful answer explaining that why python -V outputs to stderr:
Why does python print version info to stderr?
Python outputs the version to standard error (stderr) up to version 3.3 according to issue 18338 and as noted here, so redirect accordingly:
$ echo $(python --version 2>&1) | awk '{print $2}'
2.7.14
The command substitution is unnecessary and this could be written as:
$ python --version 2>&1 | awk '{print $2}'
How about using Python command itself using platform library of it(which is a very common in use).
python -c 'import platform; print(platform.python_version())'
When I run it I get Python's exact version.
Is there a way to loop in while if you start the script with python -c? This doesn't seem to be related to platform or python version...
Linux
[mpenning#Hotcoffee ~]$ python -c "import os;while (True): os.system('ls')"
File "<string>", line 1
import os;while (True): os.system('ls')
^
SyntaxError: invalid syntax
[mpenning#Hotcoffee ~]$
[mpenning#Hotcoffee ~]$ python -V
Python 2.6.6
[mpenning#Hotcoffee ~]$ uname -a
Linux Hotcoffee 2.6.32-5-amd64 #1 SMP Sun May 6 04:00:17 UTC 2012 x86_64 GNU/Linux
[mpenning#Hotcoffee ~]$
Windows
C:\Users\mike_pennington>python -c "import os;while True: os.system('dir')"
File "<string>", line 1
import os;while True: os.system('dir')
^
SyntaxError: invalid syntax
C:\Users\mike_pennington>python -V
Python 2.7.2
C:\Users\mike_pennington>
I have tried removing parenthesis in the while statement, but nothing seems to make this run.
python -c $'import subprocess\nwhile True: subprocess.call(["ls"])'
would work (note the $'...' and the \n).
But it could be that it only works under bash - I am not sure...
Multiline statements may not start after a statement-separating ; in Python – otherwise, there might be ambiguities about the code blocks. Simply use line breaks in stead of ;. This "works" on Linux:
$ python -c "import os
while True: os.system('ls')"
Not sure how to enter this on Windows, but why not simply write the commands to a .py file if it's more than one line?
Don't know about windows, if all you want is to be able to type in one-liners, you could consider line breaks inside quotes:
% python -c "import os;
while (True):
os.system('ls')"
If you really must do this in windows, you could use exec:
python -c "exec \"import os;\rwhile True:\r os.system('dir')\""
(I substituted dir so it works on my windows system)