smtp

Unix风格的可执行脚本:#!

下一个启动技术其实是前面技术的一种特殊形式,尽管这节的标题是 Unix 风格,但它可以应用到今天的 Unix 和 Windows 上运行的程序文件。因为它起源于 Unix,让我们从那里开始。

Unix风格的可执行脚本:#! —— Unix 脚本基础

如果将在 Unix,Linux 或类 Unix 系统上使用 Python,还可以将 Python 代码文件转换为可执行程序,就如同使用 shell 语言(如 csh ksh)编写程序一样。这些文件通常被称作可执行脚本。简言之,Unix 风格的可执行脚本只是包含 Python 语句的普通文本文件,但有两个特殊属性:
  • 它们的首行特殊。脚本通常以开头为 #! 字符的一行开始(通常叫作 “hash bang” 或者 “shebang”),后面跟着机器上 Python 解释器的路径。
  • 它们通常有可执行权限。脚本文件通常被标记为可执行来告诉操作系统它们可以被作为顶层程序运行。在 Unix 系统上,如 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">chmod + x file.py</font> 通常可以达到此目的。
来看一个类 Unix 系统的例子。再次使用文本编辑器来创建一个名为 brain 的 Python 代码文件:
  1. print('The Bright Side ' + 'of Life...') # + means concatenate for strings
文件顶部的特殊行告诉系统 Python 解释器在哪里。技术上讲,首行是一个 Python 注释。如前面提到的,在 Python 程序中所有注释都开始于一个 # 且扩展到行尾;它们是在代码中为人类读者插入额外信息的地方。但当像本文件中的首行那样的注释出现时,在 Unix 上它是特殊的,因为操作系统 shell 使用它来找到一个解释器,运行文件中其余部分的程序代码。 而且,注意本文件简单地被称作 brain, 没有之前用于模块文件的 .py 后缀。给名字添加 .py 不会有问题(且可以帮助你记住这是一个 Python 程序文件),但因为你没有计划让其他模块导入此文件中的代码,文件的名称是无关紧要的。如果使用 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">chmod + x brain</font> shell 命令给了文件可执行权限,可以从操作系统 shell 运行它就好像它是一个二进制程序(对下面例子,要么确保 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">.</font> (当前目录)在你系统的 PATH 设置中,或者使用 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">./brain</font> 运行):
  1. % brian
  2. The Bright Side of Life...
本文章首发在 LearnKu.com 网站上。

上一篇下一篇

Markdown 文本

纠错改进


Unix风格的可执行脚本:#! —— Unix env 查找技巧

在一些 Unix 系统上,可以通过编写如下的特殊的首行注释来避免在脚本文件中硬编码 Python 解释器的路径:
  1. ...script goes here...
当这样编码时, <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">env</font> 程序通过系统搜索路径设置(在大多数 Unix shell 中,通过查找在 PATH 环境变量中列出的所有目录)定位到 Python 解释器。这个方法更可移植,因为不需要在所有脚本的首行硬编码一个 Python 安装路径。这样,如果脚本移动到新机器,或 Python 移到新的位置,只须更新 PATH,而不是所有脚本。 假设在所有地方都可以访问到 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">env</font>, 那么不管 Python 在系统上的哪个位置,脚本都可以运行。事实上,因为一些平台可能将 Python 安装在其他地方,这个 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">env</font> 形式在今天通常被推荐,更胜于普通的如 /usr/bin/python。当然,这个方法假设 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">env</font> 在任何平台的同一个地方(在一些机器上,它可能在 /sbin, /bin 或其他地方);如果不在,那么所有便携性都会失败!

Unix风格的可执行脚本:#! —— Python 3.3 Windows 启动器:#! 来到了 Windows,e

下面都是在 Windows 平台上的操作,暂不翻译 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]
  1. C:\code> python brian
  2. 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):
  1. c:\code> type robin3.py
  2. \#!/usr/bin/python3
  3. print('Run', 'away!...') # 3.X function
  4. c:\code> py robin3.py # Run file per #! line version
  5. Run away!...
  6. c:\code> type robin2.py
  7. \#!python2
  8. print 'Run', 'away more!...' # 2.X statement
  9. c:\code> py robin2.py # Run file per #! line version
  10. 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:
  1. c:\code> py 3.1 robin3.py # Run per command-line argument
  2. 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.