python中sys.argv函数精简概括
- sys.argv[0]:给定脚本名是 ‘-‘ (标准输入)时,sys.argv[0] 是 ‘-‘。使用 -c command 时,sys.argv[0] 是 ‘-c’。如果使用选项 -m module,sys.argv[0] 就是包含目录的模块全名。
- sys.argv[1]:sys.argv[1]是输出了参数所组成的列表的第一个元素
- sys.argv[1:]:sys.argv[1:]是输出了参数所组成的列表,空格分割
1 | import sys |
python文件编码说明
python 支持3种编码声明,一般常用能见到下面两种
1 | 1.# -*- coding: utf-8 -*- |
1 | 2.短一点,但Emacs不能用# coding=utf-8 |
之所以要声明未编码类型 ,主要是中文出错的问题。
在python 文件开头(一般是第一行或第二行),用来说明你的Python源程序文件用使用的编码。缺省情况下你的程序需要使用ascii码来写,但如果在其中写中文的话,python解释器一般会报错,但如果加上你所用的文件编码,python就会自动处理不再报错。
这里要注意的是:
1.coding 后面使用 “:” 或 “=” 都可以
2.但是, “:” 或 “=” 必须和 coding之间没有空格。之前我就试过有空格声明失败,还是不支持中文。至于 “:” 或 “=” 后面,有没有空格就没所谓了。
Python -c 执行命令
1. 查看 Python 版本
1 | strong@foreverstrong:~$ python -V |
2. 查看 Python 安装路径
1 | strong@foreverstrong:~$ python -c "import sys; print(sys.executable)" |
Python -m 执行命令
在 Python3 中,只需一行命令就能实现一个简单的 HTTP 服务:
1 | python -m http.server 8000 |
执行后,在本机打开“ http://localhost:8000 ”,或者在局域网内的其它机器上打开“ http://本机ip:8000 ”,就能访问到执行目录下的内容。
与此类似,我们只需要一行命令“python -m pydoc -p xxx”,就能生成 HTML 格式的官方帮助文档,可以在浏览器中访问。
1 | python -m pydoc -p 9000 |
上面的命令执行了 pydoc 模块,会在 9000 端口启动一个 http 服务.
它的第三个常见用法是执行 pdb 的调试命令“python -m pdb xxx.py”,以调试模式来执行“xxx.py”脚本:
1 python -m pdb test.py
第四个同样挺有用的场景是用 timeit 在命令行中测试一小段代码的运行时间。以下的 3 段代码,用不同的方式拼接 “0-1-2-……-99” 数字串。可以直观地看出它们的效率差异:
1
2
3 python -m timeit "'-'.join(str(n) for n in range(100))"
python -m timeit "'-'.join([str(n) for n in range(100)])"
python -m timeit "'-'.join(map(str,range(100)))"
最后,还有一种常常被人忽略的场景:“python -m pip install xxx”。我们可能会习惯性地使用“pip install xxx”,或者做了版本区分时用“pip3 install xxx”,总之不在前面用“python -m”做指定。但这种写法可能会出问题。
-m 选项的两种原理解析
看了前面的几种典型用法,你是否开始好奇: “-m”是怎么运作的?它是怎么实现的?
对于“python -m name”,一句话解释: Python 会检索 sys.path ,查找名字为“name”的模块或者包(含命名空间包),并将其内容当成“main”模块来执行。
1、对于普通模块
以“.py”为后缀的文件就是一个模块,在“-m”之后使用时,只需要使用模块名,不需要写出后缀,但前提是该模块名是有效的,且不能是用 C 语言写成的模块。
在“-m”之后,如果是一个无效的模块名,则会报错“No module named xxx”。
如果是一个带后缀的模块,则首先会导入该模块,然后可能报错:Error while finding module specification for ‘xxx.py’ (AttributeError: module ‘xxx’ has no attribute ‘path‘。
对于一个普通模块,有时候这两种写法表面看起来是等效的:
两种写法都会把定位到的模块脚本当成主程序入口来执行,即在执行时,该脚本的 name 都是”main“,跟 import 导入方式是不同的。
但它的前提是:在执行目录中存在着“test.py”,且只有唯一的“test”模块。对于本例,如果换一个目录执行的话,“python test.py”当然会报找不到文件的错误,然而,“python -m test”却不会报错,因为解释器在遍历 sys.path 时可以找到同名的“test”模块,并且执行:
由此差异,我们其实可以总结出“-m”的用法: 已知一个模块的名字,但不知道它的文件路径,那么使用“-m”就意味着交给解释器自行查找,若找到,则当成脚本执行。
直接运行脚本时,相当于给出了脚本的完整路径(不管是绝对路径还是相对路径),解释器根据 文件系统的查找机制, 定位到该脚本,然后执行 使用“-m”方式时,解释器需要在不 import 的情况下,在 所有模块命名空间 中查找,定位到脚本的路径,然后执行。为了实现这个过程,解释器会借助两个模块: pkgutil 和 runpy ,前者用来获取所有的模块列表,后者根据模块名来定位并执行脚本
2、对于包内模块
如果“-m”之后要执行的是一个包,那么解释器经过前面提到的查找过程,先定位到该包,然后会去执行它的“main”子模块,也就是说,在包目录下需要实现一个“main.py”文件。
换句话说,假设有个包的名称是“pname”,那么, “python -m pname”,其实就等效于“python -m pname.main”。