# 关于主机
# import os
:Python 的标准库,用于调用本机操作系统的 API 。
# 关于进程
查看进程的信息:
>>> import os >>> os.geteuid() # 返回当前进程的 uid 0 >>> os.getlogin() # 返回当前终端登录的用户名 'root' >>> os.getgid() # 返回 user group id 0 >>> os.getpid() # 返回当前进程的 pid 18516 >>> os.getppid() # 返回 ppid ,也就是父进程的 pid 6484 >>> os.ctermid() # 返回当前进程的终端文件(类 Unix 系统才支持该功能) '/dev/tty'
关于环境变量:
>>> os.environ # 它存储了当前进程的所有终端环境变量,取值为 Map 类型 environ({...}) >>> os.environ.get('PATH') # 返回名为 'PATH' 的环境变量 'C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;... >>> os.environ['DEBUG'] = 'true' # 可以修改环境变量,不过只会作用于当前进程
关于工作目录:
>>> os.getcwd() # 返回当前进程的工作目录 'C:\\Users\\Leo' >>> os.chdir('D:\\') # 将工作目录,改成指定目录
# os.system()
os.system(cmd)
- 功能:创建一个终端(属于当前进程的子进程),执行一条命令。等子进程执行结束之后,将子进程的返回码(取值为 int 类型),作为该函数的返回值。
- 例:
>>> r = os.system('echo hello') hello # 子进程的 stdout、stderr 会输出到当前进程的终端 >>> r # 子进程的返回码 0
# os.popen()
os.popen(cmd, mode='r', buffering=-1)
功能:创建一个终端(属于当前进程的子进程),执行一条命令。该函数返回一个管道(pipe),用于读取子进程的 stdout 。
- 子进程的 stderr 会输出到当前进程的终端。
- 参数 mode、buffering 的作用,与 open() 函数相同。
- 实际上,
os.popen()
是对subprocess.Popen()
的封装。建议使用后者,功能更多。
os.system()
会阻塞当前进程,直到子进程运行结束。而os.popen()
会让子进程、当前进程同时运行。>>> p = os.popen('ping localhost -c 3') # 创建子进程,并开始运行 >>> p <os._wrap_close object at 0x7fedc29ba470> >>> p.read() # 读取子进程的 stdout 。如果子进程尚未结束,则会阻塞当前进程,直到子进程结束 'PING localhost.localdomain (127.0.0.1) ...'
# 关于路径
转换路径:
>>> os.path.sep # 返回本机的路径分隔符。Windows 系统通常是 '\\' ,类 Unix 系统通常是 '/' '\\' >>> os.path.normpath('/tmp/f1/') # 将一个 path 正常化(并不会判断该路径是否存在),比如转换成本机的路径分隔符 '\\tmp\\f1' >>> os.path.normpath('/tmp//f1//') # 比如去掉多余的路径分隔符 '\\tmp\\f1' >>> os.path.normpath('') # 如果输入的 path 为空字符串,则返回 '.' '.'
>>> os.path.abspath('.') # 输入一个 path ,将它转换成绝对路径 'C:\\Users\\Leo' >>> os.path.relpath('/tmp/f1', '/tmp') # 返回第一个 path ,相对于第二个 path ,的相对路径 'f1' >>> os.path.relpath('/tmp/f1', '/tmp/test/f2') '..\\..\\f1'
分割路径:
>>> os.path.split('/tmp/1.py') # 输入一个 path ,将它分割成目录名和文件名 ('/tmp', '1.py') >>> os.path.split('/tmp/') # 最后一个路径分隔符的右侧内容,会被视为文件名 ('/tmp', '') >>> os.path.split('') ('', '') >>> os.path.normpath('C:/1/2.py').split(os.path.sep) # 也可手动分割 path 这个字符串 ['C:', '1', '2.py']
>>> os.path.dirname('/tmp/1.py') # 提取目录名 '/tmp' >>> os.path.basename('/tmp/1.py') # 提取文件名 '1.py' >>> os.path.join('/tmp', '1.py') # 用本机的路径分隔符,将目录名、文件名合成一个 path '/tmp\\1.py' >>> os.path.join('/tmp', 'test', '1.py') # 可以输入多层目录,一起合并 '/tmp\\test\\1.py'
# 关于文件
获取文件的信息:
>>> os.path.exists('C:\\Users') # 输入一个 path ,判断它是否存在于本机 True >>> os.path.isfile('C:\\Users') # 判断是否为文件,而不是目录。如果该路径不存在,则也返回 False False >>> os.path.isdir('C:\\Users') # 判断是否为目录 True >>> os.path.getsize('C:\\Users') # 返回文件的体积,单位为 bytes 。如果该路径不存在,则抛出 OSError 异常 4096 >>> os.path.getctime('C:\\Users') # 返回文件的创建时间 1546567973.6038435 >>> os.path.getatime('C:\\Users') # 返回文件的最后访问时间 1562806458.460649 >>> os.path.getmtime('C:\\Users') # 返回文件的最后修改时间 1562806458.460649 >>> os.stat('C:\\Users') # 返回文件的详细信息 os.stat_result(st_mode=16749, st_ino=1407374883763938, st_dev=2351311628, st_nlink=1, st_uid=0, st_gid=0, st_size=4096, st_atime=1562806458, st_mtime=1562806458, st_ctime=1546567973)
修改文件:
>>> os.link(src, dst) # 创建硬链接。如果 dst 路径已存在,则抛出 OSError 异常 >>> os.symlink(src, dst) # 创建符号链接 >>> os.rename(src, dst) # 重命名 >>> os.remove(path) # remove a file or directory
# 关于目录
查看指定目录下的所有文件、文件夹:
>>> os.listdir('D:\\test') ['1.py', '__pycache__']
- 返回结果,包括隐藏文件,但不包括
.
和..
两个特殊文件。 - 返回结果,不包括子目录下的内容。
- 如果遇到异常(比如无权访问目标目录),则该函数不会返回任何结果。
- 返回结果,包括隐藏文件,但不包括
查看指定目录以及所有子目录的内容:
>>> os.walk('.', onerror=print) <generator object walk at 0x000001CC520EBA98> >>> for i in _: >>> print(i) >>> ('.', ['__pycache__'], ['1.py']) ('.\\__pycache__', [], [])
- 该函数的返回值是一个生成器,迭代的每个元素是一个三元组:
- 目录名
- 该目录下的文件夹列表
- 该目录下的文件名列表
- 如果遇到异常,则该函数默认会忽略异常。建议传入 onerror 参数,记录遇到的异常。
- 该函数的返回值是一个生成器,迭代的每个元素是一个三元组:
修改目录:
>>> os.mkdir(path) # 创建目录。如果该路径已存在,则抛出 OSError 异常 >>> os.makedirs('1/2/3') # 创建目录。如果中间几层目录不存在,则自动创建它们。如果最终目录已存在,则抛出 OSError 异常 >>> os.makedirs('1/2/3', exist_ok=True) # 如果最终目录已存在,则不报错 >>> os.rmdir(path) # 删除目录。要求该目录不包含任何文件、子目录。如果该目录的内容不为空,则抛出 OSError 异常
# import sys
:Python 的标准库,用于调用 Python 解释器的 API 。
关于当前进程:
>>> import sys >>> sys.argv # 返回当前进程启动时,传入的命令行参数。不过手动解析 sys.argv 比较麻烦,更推荐使用 argparse 标准库 [''] >>> sys.executable # 返回当前进程的可执行文件的路径 '/usr/bin/python3'
>>> sys.exit() # 退出当前 Python 解释器,也就是终止当前进程。默认返回 0 ,作为当前进程的返回码 >>> sys.exit(1) # 返回指定数字 >>> exit() # 也可调用内置函数 exit()
关于 Python 解释器:
>>> sys.path # 记录几个常用目录。执行 import 语句时,会到这些目录下查找文件 ['', '/usr/lib64/python36.zip', '/usr/lib64/python3.6', ...] >>> sys.modules # 取值为 dict 类型,存储当前加载的所有 Python 模块 {'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>, ...} >>> sys.platform # 返回本机操作系统的类型,比如 linux、darwin、win32 'linux' >>> sys.implementation # 返回 Python 解释器的版本信息。不过这些信息不多,更推荐使用 platform 模块 namespace(_multiarch='x86_64-linux-gnu', cache_tag='cpython-36', hexversion=50727152, name='cpython', version=sys.version_info(major=3, minor=6, micro=8, releaselevel='final', serial=0))
以下三个对象,表示当前终端的标准输入、输出、错误:
sys.stdin sys.stdout sys.stderr
- 例:写入字符串到 stdout
>>> sys.stdout # 标准输出的存在,像一个文本文件 <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'> >>> count = sys.stdout.write('hello') # 向 stdout 写入一个字符串,然后返回写入的字符数 hello
- 例:将 stdout、stderr 重定向到一个磁盘文件
>>> f = open('output.txt', 'w') >>> sys.stdout = f >>> sys.stderr = f >>> print('hello') # print() 函数会将字符串作为 stdout 输出 >>> raise RuntimeError('testing...') # 抛出异常,这会作为 stderr 输出 >>> sys.__stdout__ # 如果想恢复原来的 stdout ,则可使用该内置变量 <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
- 例:写入字符串到 stdout
关于异常:
>>> a NameError: name 'a' is not defined >>> sys.last_type # 返回最近一个异常的类型 <class 'NameError'> >>> sys.last_value # 返回最近一个异常的描述 NameError("name 'a' is not defined",)
关于对象:
>>> sys.getrefcount(object()) # 返回对象的引用计数 1 >>> sys.getsizeof(object()) # 返回对象占用的内存大小,单位为 bytes 50
# import platform
:Python 的标准库,用于查看本机的平台信息。
关于操作系统:
>>> import platform >>> platform.uname() # 返回操作系统的类型、版本等信息 uname_result(system='Linux', node='CenOS-1', release='3.10.0-1120.51.1.el7.x86_64', version='#1 SMP Tue Jun 28 15:37:28 UTC 2022', machine='x86_64', processor='Intel64 Family 6 Model 158 Stepping 10, GenuineIntel') >>> platform.system() # 返回操作系统的类型,比如 Linux、Darwin、Windows 'Linux' >>> platform.release() # 返回操作系统的版本 '3.10.0-1120.51.1.el7.x86_64' >>> platform.machine() # 返回 CPU 的架构类型。比如 x86_64、AMD64 'x86_64' >>> platform.processor() # 返回 CPU 的具体名称 'Intel64 Family 6 Model 158 Stepping 10, GenuineIntel'
关于 Python 解释器:
>>> platform.architecture()[0] # 返回本机的 CPU 字长 '64bit' >>> platform.python_version() # 返回 Python 解释器的版本 '3.6.8' >>> platform.python_version_tuple() # 将版本号,分割成三个字段 ('3', '6', '8') >>> platform.python_implementation() # 返回 Python 解释器的实现类型,比如 CPython、Jython、PyPy 'CPython'
# import psutil
:Python 的第三方库,用于监控本机的运行状态。用途像 Linux 的 ps、free 等命令。
安装:
pip install psutil
关于进程:
>>> import psutil >>> psutil.pids() # 返回本机所有进程的 PID [1, 2, 4, 6, 7, 8, 9, 10, ...] >>> psutil.pid_exists(1) # 检查指定 PID 的进程是否存在 True >>> psutil.Process(1) # 通过 PID 选中一个进程,返回一个 Process 对象。之后可以调用该对象的各个方法 psutil.Process(pid=1, name='systemd', status='sleeping', started='2022-01-15 16:00:30')
>>> p = psutil.Process(os.getpid()) # 通过 os.getpid() 获取当前进程的 PID ,然后选中当前进程 >>> p psutil.Process(pid=26002, name='python3', status='running', started='16:55:28') >>> p.pid 26002 >>> p.name() # 返回进程的名称 'python3' >>> p.status() # 返回进程的状态 'running' >>> p.create_time() # 返回进程的创建时间,取值为 Unix 时间戳 1661504128.0 >>> p.terminate() # 终止进程
>>> p.exe() # 返回进程的可执行文件的路径 '/usr/bin/python3.6' >>> p.cmdline() # 返回进程的启动命令 ['python3'] >>> p.cwd() # 返回进程的工作目录 '/root' >>> p.username() # 返回启动该进程的用户名 'root'
>>> p.parent() # 返回该进程的父进程 psutil.Process(pid=3889, name='bash', status='sleeping', started='16:28:31') >>> p.children() # 返回该进程的所有子进程 [] >>> p.num_threads() # 返回该进程的线程数 1 >>> p.threads() # 返回该进程的所有线程 [pthread(id=32123, user_time=0.06, system_time=0.0)]
查看进程的状态:
>>> p.cpu_percent(1) # 阻塞 1 秒,然后统计这段时间内,该进程的 CPU 使用率 15.6 >>> p.memory_info() # 返回该进程的内存使用信息 pmem(rss=10549008, vms=174663920, shared=3809280, text=4096, lib=0, data=6295552, dirty=0) >>> p.open_files() # 返回该进程打开的所有文件 [popenfile(path='/tmp/f1', fd=3, position=0, mode='w', flags=32769), ...] >>> p.net_connections() # 返回该进程的所有 Socket 网络连接 [pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='10.0.0.2', port=80), status='ESTABLISHED'), ...]
查看 CPU 的状态:
>>> psutil.cpu_count() # 返回本机的 CPU 总核数(默认为逻辑核数) 8 >>> psutil.cpu_count(logical=False) # 返回 CPU 物理核数 4 >>> psutil.cpu_percent() # 返回所有 CPU 的平均使用率。统计的时间范围是,从上一次调用该函数开始,到目前为止 7.2 >>> psutil.cpu_percent(interval=1, percpu=True) # 阻塞 1 秒,然后统计这段时间的各个CPU使用率 [20.6, 7.7, 10.8, 20.0, 12.3, 4.6, 10.8, 4.6] >>> psutil.cpu_times_percent() # 查看 CPU 各个维度的使用率(像 Linux 的 top 命令) scputimes(user=3.2, system=4.0, idle=92.5, interrupt=0.2, dpc=0.2)
查看内存的状态:
>>> psutil.virtual_memory() # 返回本机的内存使用量,单位为 bytes(像 Linux 的 free 命令) svmem(total=8424906752, available=2264326144, percent=73.1, used=6160580608, free=2264326144) >>> psutil.swap_memory() # 返回本机 swap 分区的使用量 sswap(total=15404228608, used=9708523520, free=5695705088, percent=63.0, sin=0, sout=0)
查看磁盘的状态:
>>> psutil.disk_partitions() # 返回本机的所有磁盘分区 [sdiskpart(device='/dev/vda1', mountpoint='/', fstype='ext4', opts='rw,relatime,data=ordered'), ...] >>> psutil.disk_usage('/dev/vda1') # 查看某个磁盘分区的使用量 sdiskusage(total=295923871744, used=237350260736, free=58573611008, percent=80.2)
查看网络的状态:
>>> psutil.net_if_addrs() # 返回本机的所有网卡地址(interface address) {'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None), ...} >>> psutil.net_connections() # 返回本机所有的 Socket 网络连接 [sconn(fd=3, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip='0.0.0.0', port=22), raddr=(), status='LISTEN', pid=1320), ...] >>> psutil.net_connections(kind='tcp') # 只返回 tcp 类型的 Socket [sconn(fd=3, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip='0.0.0.0', port=22), raddr=(), status='LISTEN', pid=1320), ...]