Python shebang not forcing other version [Mac] - python

I'm new to Python and programming in general.
I'm trying to force my scripts to use Python3.4 as installed using the python installer from python.org.
My script has this.
#!/usr/local/bin/python3.4
import sys
print(sys.version)
print("Hello, World!")
Terminal returns this:
$ python pyscript.py
2.7.5 (default, Aug 25 2013, 00:04:04)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]
Hello, World!
The shebang path is correct, according to "which python3.4"

By calling python on your script you are using the python in your path. As the comment suggests run the file directly after setting the execution bit.

Shebang is only used when you run your script directly using command like this
$ ./pyscript.py
When you python interpreter from command line, the shell doesn't consult shebang line. It simply runs the first python executable it finds on the command line.
To change the default python executable, adjust your path. Or better yet use python virtual environment. More information on virtual environment is here

Depending on your installation, python can be installed in a multitude of places on OS X.
Without any other additional changes, you are likely running the python located in /usr/bin/python. This can be verified by typing which python
~ $ which python
/usr/bin/python
Note that while /usr/local/bin/python3.4 may be the correct path to python 3.4, when you type python script.py you are not invoking the command you found when you did which python3.4.
To fix this you can do one of:
Invoke the script directly. Type script.py (with the executable bit) rather than as python script.py. You may need to change the permissions on the script to executable with chmod u+x script.py.
Change the version in /usr/bin/python to the version you want. Note that this may be very dangerous in that other things expecting the base install python of 2.7.5 can become very unhappy
Change your $PATH to put /usr/local/bin/ before /usr/bin and have python in /usr/local/bin/python point to the 3.4 version.

The shebang path is only used by the OS when you make the file executable and run it directly, like this:
chmod 755 pyscript.py
./pyscript.py
For python, the shebang is only a comment. The only way to force it even when calling the interpreter directly on the CLI is to compare the version and if it's less re-launch it using os.execv or similar. Something like this should do (not tested though):
#!/usr/local/bin/python3.4
import sys
import os
if (sys.hexversion < 0x3040000):
sys.argv.insert(0, '/usr/local/bin/python3.4')
os.execv(sys.argv[0], sys.argv)
print(sys.version)
print("Hello, World!")
You might want to use env on the shebang to avoid specifying the path, and avoid hardcoding the path on the python code too...

For example, in a python script file called script.py, in my case I have a 3.7 Python at the following path:
#! /Library/Frameworks/Python.framework/Versions/3.7/bin/python3
import sys
print("--- Python version ---")
print(sys.version)
print("--- Python version info ---")
print(sys.version_info)
print("--- Python path executable ---")
print(sys.executable)
As others say, give permissions and do a proper execution so that shebang can be applied:
In the terminal type the following to make script.py a executable file for your user, that is:
$ chmod u+x script.py
In the terminal script.py is run with ./ at the beginning (not using python):
$ ./script.py
In my case I've got:
--- Python version ---
3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 16:52:21)
[Clang 6.0 (clang-600.0.57)]
--- Python version info ---
sys.version_info(major=3, minor=7, micro=3, releaselevel='final', serial=0)
--- Python path executable ---
/Library/Frameworks/Python.framework/Versions/3.7/bin/python3
Considerations:
shebang path cannot contain spaces.
"Python path executable" not necessarily match with shebang path as long as the python at the shebang path can be an "alias". Aliases in Mac point to other file, you can see it with right click on a file and select "Get info" to check the "Original" value.

Related

Find Python Installation Directory (Specifically, Python\PythonVERSION) from python [duplicate]

Python is on my machine, I just don't know where, if I type python in terminal it will open Python 2.6.4, this isn't in it's default directory, there surely is a way of finding it's install location from here?
sys has some useful stuff:
$ python
Python 2.6.6 (r266:84297, Aug 24 2010, 18:13:38) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.executable
'c:\\Python26\\python.exe'
>>> sys.exec_prefix
'c:\\Python26'
>>>
>>> print '\n'.join(sys.path)
c:\Python26\lib\site-packages\setuptools-0.6c11-py2.6.egg
c:\Python26\lib\site-packages\nose-1.0.0-py2.6.egg
C:\Windows\system32\python26.zip
c:\Python26\DLLs
c:\Python26\lib
c:\Python26\lib\plat-win
c:\Python26\lib\lib-tk
c:\Python26
c:\Python26\lib\site-packages
c:\Python26\lib\site-packages\win32
c:\Python26\lib\site-packages\win32\lib
c:\Python26\lib\site-packages\Pythonwin
c:\Python26\lib\site-packages\wx-2.8-msw-unicode
In unix (mac os X included) terminal you can do
which python
and it will tell you.
Platform independent solution in one line is
Python 2:
python -c "import sys; print sys.executable"
Python 3:
python -c "import sys; print(sys.executable)"
For Windows CMD run: where python
For Windows PowerShell run: Get-Command python
Have a look at sys.path:
>>> import sys
>>> print(sys.path)
On UNIX-like systems, you should be able to type which python, which will print out the path to python. The equivalent in Windows Command Prompt is where python, and Get-Command python in Windows Powershell.
Another (cross-platform) method is to type this into IDLE or REPL (type python into your terminal):
import re
re.__file__
Or in one line from your terminal:
python -c "import re; print(re.__file__)"
This will print the path to the re module, consequently showing you where the python command points to. You can put any other module that you know is installed, and the path will point to that module, also giving you the path to python.
To find all the installations of Python on Windows run this at the command prompt:
dir site.py /s
Make sure you are in the root drive. You will see something like this.
If you are using wiindows OS (I am using windows 10 ) just type
where python
in command prompt ( cmd )
It will show you the directory where you have installed .
For Windows Users:
If the python command is not in your $PATH environment var.
Open PowerShell and run these commands to find the folder
cd \
ls *ython* -Recurse -Directory
That should tell you where python is installed
First search for PYTHON IDLE from search bar
Open the IDLE and use below commands.
import sys
print(sys.path)
It will give you the path where the python.exe is installed. For eg:
C:\Users\\...\python.exe
Add the same path to system environment variable.
On windows search python,then right click and click on "Open file location".That's how I did
Run below command
where python

venv not sticking across subprocess.run on python/windows?

When I make a python venv on Windows:
C:\> mkdir C:\tvenv
C:\> cd C:\tvenv
C:\> python -m venv v
And then create these three files:
t.bat
call "C:\tvenv\v\Scripts\activate.bat"
python t1.py
t1.py
import subprocess
import sys
print('T1', sys.executable)
subprocess.run(['python', 't2.py'])
t2.py
import sys
print('T2', sys.executable)
And then I run t.bat:
C:\> t.bat
OBSERVED OUTPUT
T1 C:\tvenv\v\Scripts\python.exe
T2 C:\Program Files\Python38\python.exe
The following happens:
t.bat activates a venv and calls t1.py.
t1.py correctly reports the sys.executable from the venv
t1.py then calls subprocess.run(['python', 't2.py'])
t2.py then reports the system-wide sys.executable, not the one from the venv
ie I would have expected the output to be:
EXPECTED OUTPUT
T1 C:\tvenv\v\Scripts\python.exe
T2 C:\tvenv\v\Scripts\python.exe
as activate.bat sets:
set PATH=%VIRTUAL_ENV%\Scripts;%PATH%
It puts the venv Scripts dir at the front of the PATH.
so why doesn't subprocess.run(['python']) find the venv python instead of the system-wide one?
Update
I am on latest Windows 10 x64. I just completely reinstalled Python 3.9.1 from the standard python.org Windows installer, and didn't even put it in my PATH. Problem is still present.
The issue is indeed linked to Windows behavior and in fact the main solution is to use sys.exectuable instead of python to actually launch the expected python binary instead of letting the OS resolving that by himself.
Much more explanations on the issue and how OS are impacting the behavior of subprocess.run command: https://github.com/python/cpython/issues/86207

Why can't Anaconda python in shebang line find script (cygwin)?

I use cygwin on Windows 10, and want to write Python code
that uses Pandas and other packages contained in my Anaconda base
environment. I can run Python code if I give the absolute
path to the code, but not if bash needs to use PATH
to find the code.
I use these lines in my .bash_profile as suggested
here (search for 'bash_profile'):
. /opt/conda/etc/profile.d/conda.sh
conda activate base
Here's the start of my PATH, showing Anaconda stuff at the front:
$ echo ${PATH:1:160}
cygdrive/c/Users/Glenn/Anaconda3:/cygdrive/c/Users/Glenn/Anaconda3/Library/mingw-w64/bin:/cygdrive/c/Users/Glenn/Anaconda3/Library/usr/bin:/cygdrive/c/Users/Gle...
I can run Anaconda Python at the bash prompt:
$ which python
/cygdrive/c/Users/Glenn/Anaconda3/python
$ python -i
Python 3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)] :: Anaconda, Inc. on win32
Warning:
This Python interpreter is in a conda environment, but the environment has
not been activated. Libraries may fail to load. To activate this environment
please see https://conda.io/activation
Type "help", "copyright", "credits" or "license" for more information.
>>>
I can even run a Python program that uses Pandas:
$ pwd
/home/Glenn/bin
$ cat test.py
#!/usr/bin/env python
import pandas as pd
print(pd.Series([1,2]))
$ ./test.py
0 1
1 2
dtype: int64
The problem is that I can't run the program if I rely on the path:
$ which test.py
/home/Glenn/bin/test.py
$ test.py
C:\Users\Glenn\Anaconda3\python.exe: can't open file '/home/Glenn/bin/test.py': [Errno 2] No such file or directory
$
I get the same kind of error message if I invoke test.py from
another directory using an absolute pathname, but not if I invoke
it using a relative pathname.
I'm a longtime Cygwin user and haven't seen this kind of behavior
before, so suspect it has to do with Anaconda.
I can change to any other directory and get the same behavior.
Also, if I put the absolute path to Anaconda's Python in the
shebang line, I get the same behavior.
I've found (and tried) many suggestions for configuring Anaconda in a Cygwin environment, but many of them are 4 or 5 years old.
UPDATE: I was not able to solve this problem, but have switched to the Linux Windows Subsystem and no longer have to deal with the issue.

"python myscript" ignores "#!/usr/bin/env pythonX" where pythonX doesn't exist

Why doesn't test.py throw error env: python3: No such file or directory when Python 3 is not installed?
My system (Mac OS X) has Python 2.7 installed, but not Python 3:
$ /usr/bin/env python -V
Python 2.7.12
$ /usr/bin/env python3 -V
env: python3: No such file or directory
File test.py:
#!/usr/bin/env python3
import sys
print sys.executable
Executing test.py:
$ python test.py
/usr/local/opt/python/bin/python2.7
I thought that since Python 3 does not exist on my system, having the shebang line #!/usr/bin/env python3 will throw an error and terminate the script. But env actually selected the Python 2.7 interpreter.
The shebang is interpreted by OS when it tries to execute the script. Whey you type python test.py, the OS executes python and python executes the script (and python is found based on the current PATH) as opposed to being processed by the OS.
If you make the script executable (chmod +x test.py) and then try to execute it directly (e.g. ./test.py), the OS will be responsible for running the script so it will look at the shebang to figure out what program is responsible to run the script. In this case, it is /usr/bin/env which will look for python3 and try to use that. Since python3 isn't there (or not findable on your PATH) you'll see the error.
The shebang is only processed when you do test.py, running the file directly instead of running python with test.py as an argument. When you do python test.py, Python completely ignores the shebang line.

which version of python is used when I run it in interpreter?

I am confused in trying to understand which python version is used when I run them in interpreter?
That is, how the shell decides which python version to load when I have more than one versions.
I have snapshot of my /usr/bin. It has atleast two different python versions2.5 and 2.6.
I have not specified anything in my .bashrc to choose which one from.
when I execute python command on bash shell, python interpreter opens up, but loads with version 2.6.
How is this detected by shell?
If I want to change versions, how will I do that? That is, I want to change the default version
lastly what kind of files are these in /usr/bin/python. I tried to open them in editor and I see some ###. I have read many posts here but some makes me confusing.
ls /usr/bin/python
python python2.5 python2.6 pythonw pythonw2.6
python-config python2.5-config python2.6-config pythonw2.5
python
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
To know which version is used by default, type
which python
To use another one, use the full path when invoking them:
/usr/bin/python/python2.5 myfile.py
/usr/bin/python/python2.6 myfile.py
etc.
If you want to change the default, you can create an alias in ~/.bashrc for example:
my_python='/usr/bin/python/python2.7'
or better change the link direction of /usr/bin/python (or whatever comes from which python). It is a link, so link it to the exact version you need.
ln -s /prefered/path/of/python /usr/bin/python
The files you see in /usr/bin/python are executables. You can do the following to see this:
file /usr/bin/python/python2.5
In my case:
$ file /usr/bin/python
/usr/bin/python: symbolic link to `python2.7'
$ file /usr/bin/python2.7
/usr/bin/python2.7: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xf66a10f2c444b2329b25ab6790abb7fbb4fe3f78, stripped
python --version
Then head on over to your .bashrc (should be in your home directory) and add:
alias python='[your path]'
for me I have:
alias python='/usr/bin/python2.7'
Just make sure you say:
source ./bashrc
to apply your changes.

Categories

Resources