Our next launching technique is really a specialized form of the prior, which, despite this section’s title, can apply to program files run on both Unix and Windows today. Since it has its roots on Unix, let’s begin this story there.
If you are going to use Python on a Unix, Linux, or Unix-like system, you can also turn files of Python code into executable programs, much as you would for programs coded in a shell language such as csh or ksh. Such files are usually called executable scripts. In simple terms, Unix-style executable scripts are just normal text files containing Python statements, but with two special properties:
Their first line is special. Scripts usually start with a line that begins with the characters #! (often called “hash bang” or “shebang”), followed by the path to the Python interpreter on your machine.
They usually have executable privileges. Script files are usually marked as executable to tell the operating system that they may be run as top-level programs. On Unix systems, a command such as chmod +x file.py usually does the trick.
Let’s look at an example for Unix-like systems. Use your text editor again to create a file of Python code called brian:
#!/usr/local/bin/python
print('The Bright Side ' + 'of Life...') # + means concatenate for strings
The special line at the top of the file tells the system where the Python interpreter lives. Technically, the first line is a Python comment. As mentioned earlier, all comments in Python programs start with a # and span to the end of the line; they are a place to insert extra information for human readers of your code. But when a comment such as the first line in this file appears, it’s special on Unix because the operating system shell uses it to find an interpreter for running the program code in the rest of the file.
Also, note that this file is called simply brian, without the .py suffix used for the module file earlier. Adding a .py to the name wouldn’t hurt (and might help you remember that this is a Python program file), but because you don’t plan on letting other modules import the code in this file, the name of the file is irrelevant. If you give the file executable privileges with a chmod +x brian shell command, you can run it from the operating system shell as though it were a binary program (for the following, either make sure ., the current directory, is in your system PATH setting, or run this with ./brian):
% brian
The Bright Side of Life...
On some Unix systems, you can avoid hardcoding the path to the Python interpreter in your script file by writing the special first-line comment like this:
#!/usr/bin/env python
...script goes here...
When coded this way, the env program locates the Python interpreter according to your system search path settings (in most Unix shells, by looking in all the directories listed in your PATH environment variable). This scheme can be more portable, as you don’t need to hardcode a Python install path in the first line of all your scripts. That way, if your scripts ever move to a new machine, or your Python ever moves to a new location, you must update just PATH, not all your scripts.
Provided you have access to env everywhere, your scripts will run no matter where Python lives on your system. In fact, this env form is generally recommended today over even something as generic as /usr/bin/python, because some platforms may install Python elsewhere. Of course, this assumes that env lives in the same place everywhere (on some machines, it may be in /sbin, /bin, or elsewhere); if not, all portability bets are off!
A note for Windows users running Python 3.2 and earlier: the method described here is a Unix trick, and it may not work on your platform. Not to worry; just use the basic command-line technique explored earlier. List the file’s name on an explicit python command line:[5]
C:\code> python brian
The Bright Side of Life...
In this case, you don’t need the special #! comment at the top (although Python just ignores it if it’s present), and the file doesn’t need to be given executable privileges. In fact, if you want to run files portably between Unix and Microsoft Windows, your life will probably be simpler if you always use the basic command-line approach, not Unix-style scripts, to launch programs.
If you’re using Python 3.3 or later, though, or have its Windows launcher installed separately, it turns out that Unix-style #! lines do mean something on Windows too. Besides offering the py executable described earlier, the new Windows launcher mentioned earlier attempts to parse #! lines to determine which Python version to launch to run your script’s code. Moreover, it allows you to give the version number in full or partial forms, and recognizes most common Unix patterns for this line, including the /usr/bin/env form.
The launcher’s #! parsing mechanism is applied when you run scripts from command lines with the py program, and when you click Python file icons (in which case py is run implicitly by filename associations). Unlike Unix, you do not need to mark files with executable privileges for this to work on Windows, because filename associations achieve similar results.
For example, the first of the following is run by Python 3.X and the second by 2.X (without an explicit number, the launcher defaults to 2.X unless you set a PY_PYTHON environment variable):
c:\code>type robin3.py#!/usr/bin/python3 print('Run', 'away!...') # 3.X function c:\code>py robin3.py# Run file per #! line version Run away!... c:\code>type robin2.py#!python2 print 'Run', 'away more!...' # 2.X statement c:\code>py robin2.py# Run file per #! line version Run away more!...
This works in addition to passing versions on command lines—we saw this briefly earlier for starting the interactive prompt, but it works the same when launching a script file:
c:\code> py −3.1 robin3.py # Run per command-line argument
Run away!...
The net effect is that the launcher allows Python versions to be specified on both a per-file and per-command basis, by using #! lines and command-line arguments, respectively. At least that’s the very short version of the launcher’s story. If you’re using Python 3.3 or later on Windows or may in the future, I recommend a side trip to the full launcher story in Appendix B if you haven’t made one already.
[5] As we discussed when exploring command lines, all recent Windows versions also let you type just the name of a .py file at the system command line—they use the Registry to determine that the file should be opened with Python (e.g., typing brian.py is equivalent to typing python brian.py). This command-line mode is similar in spirit to the Unix #!, though it is system-wide on Windows, not per-file. It also requires an explicit .py extension: filename associations won’t work without it. Some programs may actually interpret and use a first #! line on Windows much like on Unix (including Python 3.3’s Windows launcher), but the system shell on Windows itself simply ignores it.