Last Updated: 2023-09-28 00:29:41 Thursday
-- TOC --
本文总结Python标准库中的sys模块所涉及的知识点,这里的sys指Python系统。
sys模块的exit函数,通过抛出一个SystemExit
异常来尝试结束程序,Python代码可以捕获这个异常来进行一些程序退出前的清理工作,既然可以捕获这个异常,也就可以不退出程序。sys.exit函数同样可以带一个参数来作为程序的退出码,默认是0。
>>> import sys
>>> try:
... sys.exit(101)
... except SystemExit as e:
... print(repr(e))
... print(str(e))
...
SystemExit(101)
101
>>>
捕获了sys.exit()函数抛出的异常,处理之后,还要程序继续退出,可以直接使用exit或quit函数。实践中,完整的使用sys.exit函数的逻辑应该是如下这样的代码:
import sys
def main():
sys.exit(123)
return
if __name__ == '__main__':
try:
main()
except SystemExit as e:
if str(e) == '123':
print('---123---')
exit(123)
这两个接口一般在交互式环境下使用。它们也会抛出SystemExit异常:
>>> try:
... exit(123)
... except BaseException as e:
... print(str(e))
...
123
>>> try:
... quit(234)
... except SystemExit as e:
... print(str(e))
...
234
用Exception不能捕获SystemExit异常 ,要使用BaseException,或者直接SystemExit。
这个函数简单粗暴,就是直接退出python解释器,后面的代码都不执行了!一般程序不推荐使用这种退出方式。
在python线程中,使用sys.exit(包括exit和quit),都只能实现退出子线程,而不能退出主线程。如果在子线程中调用os._exit,可以实现整个进程的退出。
常常在Windows系统找不到Python安装位置,打印这个变量即可。
C:\Users\xinli>python -c "import sys;print(sys.executable)"
C:\Users\xinli\AppData\Local\Programs\Python\Python37\python.exe
D:\temp>where python
C:\Users\Administrator\AppData\Local\Programs\Python\Python38\python.exe
C:\Users\Administrator\AppData\Local\Programs\Python\Python39\python.exe
C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps\python.exe
sys模块下有一对函数,getswitchinterval和setswitchinterval,用来获取和修改python线程的切换间隔。后来在网上查了一下,资料极少。比较有价值的是这篇帖子:https://stackoverflow.com/questions/7376776/sys-setswitchinterval-in-python-3-2-and-beyond
其中有Tim Peter的一句话,说99%的人都不需要用到修改默认的switch interval。
补充一下,通过sys.getswitchinterval,可以得知python3系统默认的线程切换间隔是5毫秒。
GIL的存在使得多Python线程不能利用多核CPU并行执行!5毫秒强制切换线程,具体哪个线程能够被执行,还要靠OS调度。
得到Python对象的字节大小!
>>>import sys
>>> sys.getsizeof([1,2,3,4,5,6])
112
>>> sys.getsizeof((1,2,3,4,5,6))
96
>>> sys.getsizeof('123456')
55
>>> sys.getsizeof(123456)
28
>>> sys.getsizeof(1.23456)
24
list对象比tuple更消耗内存。
>>> d = {'1':1,'2':2,'3':3,'4':4,'5':5,'6':6}
>>> sys.getsizeof(d)
368
>>> s = set((1,2,3,4,5,6))
>>> s
{1, 2, 3, 4, 5, 6}
>>> sys.getsizeof(s)
736
看起来set对象比dict对象还要占内存,同样存放6条记录,set对象占用内存是dict的一倍。但它们都比list还要多。所以,如果你的python程序占用内存太多,能用tuple的地方,就别用list!
还有,可以考虑使用generator来减少内存占用。
>>> a = [x for x in range(100)]
>>> sys.getsizeof(a)
912
>>> b = (x for x in range(100))
>>> sys.getsizeof(b)
120
得到当前系统的默认字节序。
>>> import sys
>>> sys.byteorder
'little'
Python中都是对象,变量都是对象的引用,这有点像C语言的指针。sys模块指的是Python这个系统,sys.getrefcount接口可以查询解释器内对象的引用计数。当对象的引用计数为0时,Python会自动收回这个对象所占用的内存空间。
sys.getrefcount返回的计数,总是比实际多1,因为包含了调用此函数的临时计数。
>>> import sys
>>> a = 1
>>> sys.getrefcount(a)
1080
>>> b = a
>>> sys.getrefcount(a)
1081
>>> c = [1,2,3]
>>> sys.getrefcount(c)
2
>>> d = c
>>> sys.getrefcount(c)
3
>>> del d
>>> sys.getrefcount(c)
2
1的引用计数好多,python系统内部很多地方都在使用1。
del语句会让引用计数减少。
默认在对应引用计数为0的时候,python内部的垃圾回收机制会将此对象所占用的内存收回。
import会优先查找当前目录!文件名一定不要和要import的模块相同,比如不要定义test.py。
Python解释器的包搜索路径。
>>> from pprint import pprint
>>> import sys
>>> pprint(sys.path)
['',
'/usr/local/python3.8.6/lib/python38.zip',
'/usr/local/python3.8.6/lib/python3.8',
'/usr/local/python3.8.6/lib/python3.8/lib-dynload',
'/home/xinlin/.local/lib/python3.8/site-packages',
'/usr/local/python3.8.6/lib/python3.8/site-packages']
$ python3 -c 'print("\n".join((__import__("sys").path)))'
/usr/local/python3.8.6/lib/python38.zip
/usr/local/python3.8.6/lib/python3.8
/usr/local/python3.8.6/lib/python3.8/lib-dynload
/home/xinlin/.local/lib/python3.8/site-packages
/usr/local/python3.8.6/lib/python3.8/site-packages
$ python3 -m site
sys.path = [
'/home/xinlin/repos',
'/usr/local/python3.8.6/lib/python38.zip',
'/usr/local/python3.8.6/lib/python3.8',
'/usr/local/python3.8.6/lib/python3.8/lib-dynload',
'/home/xinlin/.local/lib/python3.8/site-packages',
'/usr/local/python3.8.6/lib/python3.8/site-packages',
]
USER_BASE: '/home/xinlin/.local' (exists)
USER_SITE: '/home/xinlin/.local/lib/python3.8/site-packages' (exists)
ENABLE_USER_SITE: True
sys.path的初始值会受到PYTHONPATH、PYTHONHOME等环境变量的影响。可以在脚本运行过程中动态修改sys.path从而import自己需要的模块。
可以用来判断当前Python运行的底层OS系统:
>>> sys.platform
'linux'
>>> sys.platform
'win32'
更好更准确的判断底层OS系统的方式,是使用标准的platform
库:
>>> import platform
>>> platform.system()
'Windows'
>>> import platform
>>> platform.system()
'Linux'
据说使用platform方法可以返回当前操作系统的类型,Windows?Linux?OS X?Unix?FreeBSD?它能比较详细的区分。(其他的一般只能识别Windows和非Windwos)
通过sys模块的两个接口,可以控制Python解释器递归的深度。
>>> sys.getrecursionlimit()
1000
>>> sys.setrecursionlimit(200)
>>> sys.getrecursionlimit()
200
一般不用修改这个值,在调试自己的递归代码时,可以尝试修改,以方便调试。
Python系统中的int整数,并不是无限大,而是有一个很大的长度限制,最小是640数字位(640个十进制的数字)。想想64bit的整数最大才长度才20个数字位。这个限制可以通过sys模块修改:
>>> sys.get_int_max_str_digits()
4300
>>> sys.set_int_max_str_digits(640)
>>> int('9'*640)
999999999999999.....
>>> int('9'*641)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Exceeds the limit (640) for integer string conversion: value has 641 digits; use sys.set_int_max_str_digits() to increase the limit
本文链接:https://cs.pynote.net/sf/python/202206031/
-- EOF --
-- MORE --