Python shebang line with Python3 - linux

I have the following python file:
vagrant#vagrant-ubuntu-trusty-64:~/my_app$ cat version_py3.py
#!/usr/bin/env python3
print "Python 2 print statement"
and I thought python version_py3.py will enforce the use of python3. But the code ran fine. and python3 version_py3.py gives expected error.
vagrant#vagrant-ubuntu-trusty-64:~/my_app$ python3 version_py3.py
File "version_py3.py", line 3
print "Python 2 print statement"
^
Also, there is no /usr/bin/env folder on my linux. Am I missing something here with the shebang right, but Python 2 and Python 3 are both installed on my computer.
vagrant#vagrant-ubuntu-trusty-64:~/my_app$ python -V
Python 2.7.6
vagrant#vagrant-ubuntu-trusty-64:~/my_app$ python3 -V
Python 3.4.3
vagrant#vagrant-ubuntu-trusty-64:~/my_app$

When you execute a script and you want have the shebang line respected, you may not prepend "python" in the command. A binary executable as the head of a command, which could work in she-bang as well, any given she-bang is ignored because the command executable is always preferred by the kernel.
Example: So let's assume you have a little python script, but with cat in the shebang. What happens when you set the executable bit of the script and call it as the command head is that the system first reads the first line, strips off the initial two bytes and tries to execute the (mandatorily binary) executable and feed it the script file.
$ /tmp/getver
#!/bin/cat
import sys
print( sys.version )
And now try and see yourself prepending python, python2 and/or python3.
Trivia: The interpreter may choose to process the shebang another time, on its own. E.g. perl used to respect any flags like -w given, whether it is given on the shebang or on the command, no matter if perl is the command head.

Try to located the python installation with locate for example, and set it in your shebang, like #!/usr/bin/python3.6 . I bet it's here.

I am not sure if you have found the solution. In python3, the syntax for print is different. The message has to be inside the parenthesis.
Try print("Python 2 print statement")

Related

python3: How can I run a python script when python starts?

I have a shortcut which runs python3 in a terminal window. I would like to add some import commands to a python script which is to be run when python starts.
How can I do this?
eg; I have xfce4-terminal -e python3 which starts a graphical terminal session with python3 running. I want to add something to this to make python3 execute a script, however I do not want python to exit at the end of the script, which is the default behaviour if a filename is given immediatly following the python3 command.
See python --help. It mentions an environment variable called PYTHONSTARTUP which looks like it could help you get where you want.

How to run python script with arguments in python 3 interpreter?

I am using PyZo(with python3.5) and dont know how to run a script with arguments from PyZo's python interpreter - or from python interpreter in general. I found following working example here for python3 but dont know how to pass arguments (e.g. csv file input_data.csv) to the script
>>> exec(open("./script.py").read())
This is working in iPython:
In [1]: run script.py input_data.csv
What is the python 3 equivalent of the iPython command above ?
Thanks
Note 1
When running a script with arguments from an OS command line you type this:
$ python script.py input_data.csv
What I would expect when using python interpreter is being able to run a python script e.g. like this:
>>> script.py input_data.csv
i.e. without calling python executable, or using 'exec(open("./script.py").read())', etc.
For me running a script with arguments is very fundamental thing to do but apparently not for majority of users.
>>> import subprocess
>>> subprocess.run('python script.py input_data.csv', shell=True)

Python: which directory to work from

I'm on Windows 7 and using Python 3.6. The PATH has C:\Python36-32 and C:\Python36-32\scripts. This is my first foray into Python and I am working with a one line script which is merely:
print("hello")
and I'm already running into trouble.
I installed Python into C:\Python36-32. I saved hello.py to C:\Users\shea\Documents. If I open IDLE and try
>>> C:\Python36-32\python.exe C:\Users\shea\Documents\hello.py
SyntaxError: unexpected character after line continuation character
or
>>> python.exe hello.py
SyntaxError: invalid syntax
The first attempt came from a question or other reading somewhere else, I've been searching for over 2 hours for this question, that said that the complete path to the program needs to be given. Apparently, I need to add something else to another PATH to get to just using python ..., but I'm not worried about that at the moment. The 2nd attempt is just me trying something apparently easy out of frustration and that doesn't work either. I get the same problems with cmd. I don't know what is behind either problem. From the questions I've looked at, Python doesn't like more text after "\", but I don't know how I'd say what the name of the script is that I want to run with python.exe.
I think part of the problem is that the script is not in the same directory as python.exe, but I am not sure of that. Can I work with Python this way? If so, what is the right syntax to get Python to return the simple "hello" in IDLE or the cmd terminal?
The IDLE is not the same as a terminal shell.
You can do: File -> Open and open your file then Run it from Run menu or by pressing F5.
When you run IDLE you are running the python interpreter, not a regular shell. The python interpreter works on a specific directory, which you can check by doing:
>>> import os
>>> os.getcwd()
The directory it will output it's the directory the interpreter is currently in. You can change the directory the interpreter is currently in by doing:
>>> os.chdir(r'C:\Users')
In this case i changed the directory to 'C:\Users'. You can run os.getcwd() again to confirm the directory changed.
Withing the interpreter, you can run scripts using the import(<path_to_script>) call:
>>> import(r'myscript.py')
Since i only gave the name of the file, it will search for the file on the directory the interpreter is in. Since i put the interpreter in 'C:\Users', it'll look for a 'C:\Users\myscript.py' file and run the code in it. You can also pass the complete path to the import call, in which case it'll run the script no matter where the interpreter is currently in. The r before the string just tells python to take the string as it is and to not look for special characters. This is important because if you indicate your paths using \ then python would take the next letter after every \ as a special character, and would not read the path correctly (for instance, \n is a special character which indicates a new line).
If you import a script, and then do changes to it, to run it again, use the reload call:
>>> reload(r'myscript.py')
If you just want to run this on a regular terminal you just need to do:
python <script_file>
Provided the folder to the python binary is already in the environment variable PATH of Windows. In a regular shell, what you have to put on <script_file> follows the same rules as if it were on the python interpreter: if your command shell is already in directory of your script, then give just the name of the file, otherwise give the complete path, using "" and /.

Why does a bash script require an execute bit if a windows batch script can just be executed?

Yesterday I ran into the git execute bit bash script quirk - the one that requires:
git update-index --add --chmod=+x scriptname.sh
and it seemed strange to me that it was even possible to get stuck in this situation. (Ie having created a script file that you don't have permission to run).
If I have created a shell script - surely I can run it under the permissions of the shell execute permissions. Why would it need it's own execute permission bit?
My question is: Why does a bash script require an execute bit if a windows batch script can just be executed?
To run a script you have two options in unix like systems. First Option is to use a direct interpreter call with the script as parameter.
# run a bash script
bash test.sh
# run a python scripts
python test.py
The second option is mark your file as executable, with the execute bit and after a call like this ...
# sample bash
./test.sh
# sample python
./test.py
... your system tries to find the right interpreter for you. For this the first line 'shebang' of the script is used.
Bash example:
#!/bin/bash
# points to the installed bash interpreter - bash example
Python example:
#!/usr/bin/python
# points to the installed python interpreter
To your question windows only use the file extension to detect a executable file.
Well, Linux is not Windows. Linux/Unix file systems support the executable bit to distinguish executable from pure data files, and to control exec permissions for user|group|others. You can still run the script if you prefix it with the name of the shell/binary you want to start it with, but if you want to do ./scriptname.sh or execute it from the path it needs to be flagged as executable for you as the onwer|a group member|some other user, and for scripts usually the shebang in the first line that defines the interpreter to start the script with: #!/bin/bash.

Anyway to change the default exec call length?

I have a bash script and will have the first line start with # and followed by the command to execute the script, and it seems the limitation is 80 characters due to the exec call has such limitation, is there anyway to change that ? because sometimes my path will be very long.
Update.
My case is that I use virtualenv to generate a clean python environment. And in this environment, there's one executable file called pip, the shebang line is python executable path and sometimes this path will be very long, e.g.
#!/Users/myname/github/myproject/virtualenv_python3.4/bin/python3.4
If you don't want to modify your path to include the directory in which the executable, you can create a simple wrapper:
#!/bin/bash
/Users/myname/github/myproject/virtualenv_python3.4/bin/python3.4 <(cat <<"EOF"
# Python script goes here
EOF) "$#"

Resources