增加一个变量
Python脚本的运行并非天马行空,它取决于不同的平台和启动方式,Python程序可能有各种特定的环境,即程序启动时,操作系统会自动传给程序的信息。比如,脚本可以获取如下几类系统级的输入和接口:
当前工作路径(CWD)
os.getcwd
可以获取脚本启动目录,许多文件工具隐式地使用该变量。
命令行参数
sys.argv
可以获取在命令行键入的启动参数,将其作为脚本的输入。
shell变量
os.environ
可以获取运行它的shell(或父程序)中命名的变量,并传给脚本。
标准流
sys.stdin
、sys.stdout
和sys.stderr
是三个核心的命令行shell工具,负责输入/输出流,他们可以被脚本以如下方式使用:print
,os.popen
调用以及subprocess
模块,io.StringIO
l类等。
当前工作路径
当前工作路径(CWD)在脚本的执行中是一个重要概念。除非指定绝对路径,否则当脚本处理文件时将始终默认他们存在于CWD。脚本可以使用os.getcwd
获取明确的CWD路径,使用os.chdir
可以改变它的CWD。
谨记,没有完整目录路径的文件名将被映射到CWD路径,和你的PYTHONPATH
设置无关。从技术上讲,一个脚本总是启动于CWD,而非它所在的目录。反之,import
永远首先先搜索文件所在目录,而非CWD
(除非该脚本刚好在CWD目录)。
CWD、文件和import路径
当你输入一个shell命令行,比python dir1\dir2\file.py
来运行该脚本时,CWD是你键入该命令时所处的路径,而非dir1\dir2
。另一方面,Python自动将脚本所在的目录添加到模块搜索路径的最前面,因而无论如何从哪里运行,file.py总是可以导入dir1\dir2
中的其他文件。我们写一个简单的脚本,打印出它的CWD和模块搜索路径来说明:
1 | import os, sys |
现在,在该脚本所在路径运行它,CWD会如预期所设,同时该路径将会加到模块搜索路径的最前面。当在交互模式下运行时,它的第一个实体可能是一个空字符串:
但是如果我们早别的路径下运行该脚本,CWD将会随之而变(即我们输入命令的路径),并且Python会把脚本所在路径添加到木块搜索路径最前面,从而使得脚本能够看到它所在的目录的所有文件。
实际效果是,脚本没有目录路径的文件名将被映射到输入命令行的地方(os.getcwd
),而通过sys.path
列表中的首项,import
总是可以看到当前正在运行脚本的路径,最后,当通过单机图标执行一个脚本时,CWD将被设置为该文件的所在路径。
在这种情况下,文件名所用的CWD以及第一个模块搜索路径都将是该脚本所在路径。有一下两个陷阱需要避免:
- 如果不确定脚本的执行路径,最好使用完整的目录路径限定文件名。
- 命令行脚本不能总是依赖于CWD来导入不在它所处目录的文件,而应使用
PYTHONPATH
的设置和包导入路径来访问其他目录中的模块。
命令行参数
Python可以通过sys
模块获取脚本启动时命令行的输入信息,通常,他们被称为命令行参数,以内置字符串列表的形式存在于sys.argv
中,C语言的程序员可能注意到它和C的argv
数组类似,交互命令行方式启动,的Python没有命令行参数被传入,所以argv
将是空串。
1 | import sys |
如同函数参数的作用,命令行参数扮演着同样的角色,他们都为程序传递可变信息。由于不需要编码,他们时脚本更通用,比如,一个人间处理脚本可以使用一个命令行参数传递要处理的文件名,还可以处理模式的flag、Internet地址等。
解析命令行参数
一旦使用命令行参数,你会发现直接操作参数列表是不容易的。更具代表性的是,程序在启动的时候将它们转为更易用的结构。举例说明,这个脚本是扫描argv
列表查找-optionname optionvalue
值对,并以optionname
为键值保存到字典结构中方便使用。
1 | "collect command-line options in a directionary" |
你可以在你的命令行工具中导入并使用该函数,在独立运行时,它将打印如下格式化的参数字典:
1 | python testargv.py |
自然地,我们还可以为它增加参数模式、错误检查等复杂功能。对于更复杂的命令行,我们可以使用Python标准库中的命令行处理工具来解析:
getopt
模块,仿效Unix/C中的同名工具。optparse
模块,一个新的替代只选,通常认为它的功能更强大。
Python库手册中对二者都有介绍,同时提供了使用示例,通常,脚本可配置性越高,命令行处理逻辑的复杂度就越高。