目录
1. 系统类
--------------------- 解释器 ---------------------
system 执行系统命令
wait 等待任意子进程
waitpid 等待指定的子进程
kill 指定杀死进程
abort 立即中止解释器
pipe 管道操作
--------------------- 随机字符 ---------------------
urandom 生成随机字节序列
--------------------- 软硬链接 ---------------------
link 创建硬链接
symlink 创建软链接
readlink 获取软链接的实际地址
--------------------- 分隔符 ---------------------
seq 代替不同系统分隔符
altsep 替代路径分隔符
2. 环境类
environ 环境变量
device_encoding 返回字符集编码
devnull 空设备
3. 路径类
chdir 更改当前路径
path 定义/获取/判断 文件目录
curdir 当前目录
4. 文件/目录类
--------------------- 常见操作 ---------------------
open 操作文件
read 读取文件
fdopen:打开文件
close 关闭文件/套接字
closerange 关闭一定范围的文件描述符
lseek 移动文件指针
chmod 修改文件/目录权限
--------------------- 文件内容 ---------------------
write 写入内容到文件
dup2 将内容覆盖到文件中
truncate 截取文件大小
--------------------- 创建删除移动 ---------------------
makedirs 创建目录
remove 删除文件
rmdir 删除空目录
removedirs 递归删除空目录
rename 移动文件
renames 重命名目录
access 判断文件
5. 获取信息类
--------------------- 系统 ---------------------
uname 获取系统信息
times 获取进程运行时间、cpu时间
cpu_count 获取CPU核心数
get_terminal_size 获取终端窗口宽和高
linesep 获取当前系统的换行符
--------------------- 文件 ---------------------
lstat 获取文件详细信息
fstat 获取文件设备号
extsep 获取后缀
--------------------- 目录 ---------------------
getcwd 获取当前路径
listdir 列出目录下的文件/目录
scandir 遍历目录树
--------------------- 用户进程 ---------------------
getlogin 获取登录用户名
getpid 获取当前进程PID
getppid 获取当前进程PPID
1. 系统类
--------------------- 解释器 ---------------------
system 执行系统命令
语法
#执行单条命令
os.system('命令')
#执行多条命令
os.system('命令1 ; 命令2 ; 命令3') #Linux使用 ; 分隔
os.system('命令1 & 命令2 & 命令3') #Windows使用 & 分隔
举例(Linux)
path = '/home/yt/tmp'
os.system(f'cd {path} ; pwd')
wait 等待任意子进程
语法
os.wait()
如果只指定一个 wait,那么只会等待一个子进程,继续执行指令,而另外的子进程将不会等待
import os, time, subprocess
#输出开始日志
print('[{}] 启动3个子进程, 分别运行2、3、7秒'.format(time.strftime('%Y-%m-%d %H:%M:%S')))
# 启动多个子进程
p1 = subprocess.Popen(['sleep', '2'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['sleep', '3'], stdout=subprocess.PIPE)
p3 = subprocess.Popen(['sleep', '7'], stdout=subprocess.PIPE)
# 等待任意一个子进程
os.wait()
print('[{}] 等待任意一个子进程结束'.format(time.strftime('%Y-%m-%d %H:%M:%S')))
# 执行下一条指令
print('[{}] 开始执行其他指令'.format(time.strftime('%Y-%m-%d %H:%M:%S')))
- 可以看到等待了第1个子进程(2秒),另外2个子进程并没有等待,直接开始运行下一条指令
使用循环,等待所有子进程结束,才会执行下一条指令
import os, time, subprocess
# 启动多个子进程
p1 = subprocess.Popen(['sleep', '1'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['sleep', '3'], stdout=subprocess.PIPE)
p3 = subprocess.Popen(['sleep', '7'], stdout=subprocess.PIPE)
# 循环等待子进程结束
while True:
try:
# 等待任意子进程的结束
pid, status = os.wait()
# 输出日志
print('[{}] 子进程{}已退出'.format(time.strftime('%Y-%m-%d %H:%M:%S'), pid))
except OSError:
# 所有子进程全部退出,跳出循环
print('子进程已全部退出')
break
waitpid 等待指定的子进程
- 这个子进程必须是程序本身的子进程
语法
os.waitpid([PID] , [选项])
选项包含:
os.WUNTRACED:必须等待子进程结束,才能执行下一条指令
os.WNOHANG:不论子进程是否结束,都将执行下一条指令
举例(必须等待子进程结束)
import os
import subprocess
# 启动一个子进程
p = subprocess.Popen(['sleep', '8'], stdout=subprocess.PIPE)
# 等待子进程的结束
os.waitpid(p.pid, os.WUNTRACED)
# 执行下一条指令
print('下一条指令')
举例(无须等待子进程结束,直接执行下一条)
import os
import subprocess
# 启动一个子进程
p = subprocess.Popen(['sleep', '8'], stdout=subprocess.PIPE)
# 不用等待子进程的结束
os.waitpid(p.pid, os.WNOHANG)
# 执行下一条指令
print('下一条指令')
kill 指定杀死进程
语法
os.kill([PID], [信号])
例如
os.kill(52700, signal.SIGTERM)
开启一个sleep窗口,另一个窗口执行kill
sleep 窗口被终止
abort 立即中止解释器
- os.abort()函数的使用应该非常谨慎,因为它可能会产生未知的结果并导致进程中止。通常情况下,os.abort()函数只应该在严重的或不可恢复的错误发生时使用,以防止进一步的数据损坏或安全问题。
>>> print('aaa')
>>> os.abort() #立即终止
>>> print('bbb')
aaa
pipe 管道操作
- pipe() 函数可以用于创建一个管道,允许两个进程之间进行通信。管道是两个进程之间的单向通信机制,其中一个进程将数据写入管道,而另一个进程可以从管道中读取数据。
# 创建管道(读/写)
read_fd, write_fd = os.pipe()
# 创建子进程
pid = os.fork()
if pid == 0:
# 子进程中,关闭管道的写入端
os.close(write_fd)
# 从管道读取数据并输出
data = os.read(read_fd, 1024)
print("子进程收到的消息:", data.decode("utf-8"))
# 关闭管道的读取端
os.close(read_fd)
print("子进程终止")
else:
# 父进程中,关闭管道的读取端
os.close(read_fd)
# 写入数据到管道
message = "我是父进程"
os.write(write_fd, message.encode("utf-8"))
# 关闭管道的写入端
os.close(write_fd)
print("父进程终止")
--------------------- 随机字符 ---------------------
urandom 生成随机字节序列
语法
os.urandom([大小]) #大小:整数
#生成随机字节序列
>>> print(os.urandom(2))
b'\xebP'
#转换为十六进制
>>> print(os.urandom(1).hex())
cf
>>> print(os.urandom(2).hex())
c8fb
>>> print(os.urandom(5).hex())
ccebf9996b
--------------------- 软硬链接 ---------------------
link 创建硬链接
语法
os.link('[源文件]', '[硬链接路径/名称]')
例如
os.link('./tmp.txt', './link_tmp.txt')
symlink 创建软链接
语法
os.symlink('源文件' , '软链接')
举例(为 /data/tmp.txt 创建一个软链接,指向 /data/link_tmp.txt)
os.symlink('/data/tmp.txt' , '/data/link_tmp.txt')
readlink 获取软链接的实际地址
语法
os.readlink('[软链接路径]')
查看python的源路径
>>> print(os.readlink('/bin/python'))
/usr/local/bin/python3.8
--------------------- 分隔符 ---------------------
seq 代替不同系统分隔符
# windows
>>> path = "a" + os.sep + "b" + os.sep + "c.txt"
>>> print(path)
a\b\c.txt
# Linux
>>> path = "a" + os.sep + "b" + os.sep + "c.txt"
>>> print(path)
a/b/c.txt
altsep 替代路径分隔符
通过os.altsep
来插入一个替代的路径分隔符,以确保该代码在跨平台时能够正确拼接路径。
- windows使用:\
- Linux使用:/
>>> path = '/home' + os.altsep + 'yt'
>>> print(path)
/home/yt
2. 环境类
environ 环境变量
只能获取 export 输出的环境变量,/etc/profile 中的变量是无法获取的
print(os.environ)
无参数以键值对形式返回
设置参数
print(os.environ['PATH'])
获取 export 包含的变量
如果 /etc/profile 中的变量没有出现在 export 中,是无法获取的
增加或修改变量
os.environ['变量名'] = '变量路径'
修改os.environ
中的环境变量只会影响当前程序的环境变量,而不会影响操作系统中的环境变量
例如,将当前程序的字符集修改为英文
os.environ['LANG'] = 'en_US.utf8'
print(os.environ['LANG'])
device_encoding 返回字符集编码
print(os.device_encoding(0))
devnull 空设备
Linux将信息写入一个空设备
with open(os.devnull, 'w') as n:
print('aaa', file=n)
Windows将信息写入一个空设备
with open(os.devnull, 'w') as n:
print('aaa', file=n, flush=True)
flush=True
参数打开空设备,以确保输出被立即写入设备
3. 路径类
chdir 更改当前路径
#查看当前路径
>>> print(os.getcwd())
C:\Users\yt\test
#修改当前路径
>>> path = r'C:\Users\yt\abc'
>>> os.chdir(path)
#再次查看当前路径
>>> print(os.getcwd())
C:\Users\yt\abc
path 定义/获取/判断 文件目录
语法
os.path.[类型]
类型包含:
os.path.abspath(path):将相对路径转换为绝对路径。
os.path.dirname(path):返回路径的目录部分。
os.path.basename(path):返回路径的文件名部分。
os.path.exists(path):检查路径是否存在。
os.path.isfile(path):检查路径是否为文件。
os.path.isdir(path):检查路径是否为目录。
os.path.join(path, *paths):在给定的路径中添加一个或多个路径组件,返回拼接后的路径。
os.path.split(path):将路径拆分为目录和文件名部分,返回二元组。
os.path.splitext(path):将路径拆分为文件名和扩展名部分,返回二元组。
举例
# 获取当前工作目录
>>> cwd = os.getcwd()
>>> print("当前工作目录:", cwd)
当前工作目录: /home/yt/python
# 将相对路径转换为绝对路径
>>> abs_path = os.path.abspath("test.txt")
>>> print("绝对路径:", abs_path)
绝对路径: /home/yt/python/test.txt
# 检查路径是否存在,是否为文件或目录
>>> print("是否存在:", os.path.exists(abs_path))
>>> print("是否为文件:", os.path.isfile(abs_path))
>>> print("是否为目录:", os.path.isdir(abs_path))
是否存在: True
是否为文件: True
是否为目录: False
# 获取路径的目录和文件名部分
>>> dir_path, file_name = os.path.split(abs_path)
>>> print("目录部分:", dir_path)
>>> print("文件名部分:", file_name)
目录部分: /home/yt/python
文件名部分: test.txt
# 将路径组件拼接为一个路径
>>> path = os.path.join(dir_path, "new_test.txt")
>>> print("拼接后的路径:", path)
拼接后的路径: /home/yt/python/new_test.txt
# 获取文件名和扩展名部分
>>> file_name, ext_name = os.path.splitext(path)
>>> print("文件名部分:", file_name)
>>> print("扩展名部分:", ext_name)
文件名部分: /home/yt/python/new_test
扩展名部分: .txt
curdir 当前目录
>>> print(os.curdir)
.
指定文件名,分别获取相对路径、绝对路径
>>> relative_path = os.path.join(os.curdir, 'tmp.py')
>>> print('相对路径:', relative_path)
相对路径: .\tmp.py
>>> absolute_path = os.path.abspath(relative_path)
>>> print('绝对路径:', absolute_path)
绝对路径: C:\Users\yt\tmp.py
4. 文件/目录类
--------------------- 常见操作 ---------------------
open 操作文件
语法
os.open("[文件名]", [操作类型])
操作类型包含:
os.O_RDONLY:以只读模式打开文件。
os.O_WRONLY:以只写模式打开文件。
os.O_RDWR :以读写模式打开文件。
os.O_APPEND:以追加模式打开文件。
os.O_CREAT :如果不存在则创建新文件。
os.O_EXCL :与 O_CREAT 一起使用,如果文件已经存在则抛出异常。
os.O_TRUNC :打开文件时截断文件内容。
举例
#打开文件并读取内容
fd = os.open("tmp.txt", os.O_RDONLY)
#将内容赋值给变量
data = os.read(fd, 1024)
#关闭该文件
os.close(fd)
#输出文件内容
print("文件内容为:", data)
read 读取文件
语法
os.read([文件描述符], [字节长度])
读取某个文件3个字节
#打开文件,获取文件描述符
>>> fd = os.open('./tmp.py', os.O_RDONLY)
#通过os模块的描述符读取内容(只能用os中的open,内置函数open是无法读入的)
>>> result = os.read(fd, 3)
#关闭文件
>>> os.close(fd)
#输出内容
>>> print(result)
abc
读取全部内容(先获取文件大小,再指定大小)
#打开文件,获取文件描述符
>>> fd = os.open('./tmp.py', os.O_RDONLY)
# 获取文件大小
>>> file_size = os.fstat(fd).st_size
#通过os模块的描述符读取内容
>>> result = os.read(fd, file_size )
#关闭文件
>>> os.close(fd)
#输出内容
>>> print(result)
abcdefghijk
fdopen:打开文件
语法
os.fdopen(
fd, #int类型,表示要转换的文件描述符
mode='r', #文件的打开模式
buffering=-1, #缓冲模式
encoding=None, #指定文件的编码方式
errors=None, #文件编码错误处理方式
newline=None, #定换行符的转换模式
closefd=True, #表示是否在关闭文件对象时关闭文件描述符
opener=None #指定自定义文件打开器函数
)
示例
>>> fd = os.open('tmp.txt', os.O_RDONLY) #以只读模式打开文件,返回文件描述符
>>> f = os.fdopen(fd, 'r') #将文件描述符转换为文件对象
>>> print(f.read()) #读取文件内容
>>> f.close() #关闭文件对象
临时文件,临时内容
close 关闭文件/套接字
# 打开一个文件
file = open(r'C:\Users\yt\test\tmp.py')
# 获取文件描述符
fd = file.fileno()
# 关闭文件描述符
os.close(fd)
closerange 关闭一定范围的文件描述符
os.closerange()
函数在打开了大量的文件描述符时非常有用,它可以用于一次关闭所有文件描述符而不需要一个一个地关闭。
# 打开一些文件并获取它们的文件描述符
file1 = open('/home/yt/file1.txt')
file2 = open('/home/yt/file2.txt')
f1 = file1.fileno()
f2 = file2.fileno()
# 关闭一定范围的文件描述符
os.closerange(f1, f2)
lseek 移动文件指针
with open("tmp.txt", "rb") as f:
# 先读取文件内容,并打印文件指针的当前位置
content = f.read()
print("文件指针的当前位置为:", f.tell())
# 将文件指针移动到文件开头
f.seek(0, 0)
print("将文件指针移动到文件开头,文件指针的当前位置为:", f.tell())
# 将文件指针移动到文件末尾
f.seek(0, 2)
print("将文件指针移动到文件末尾,文件指针的当前位置为:", f.tell())
# 将文件指针向后移动 10 个字节
f.seek(10, 1)
print("将文件指针向后移动 10 个字节,文件指针的当前位置为:", f.tell())
输出结果
文件指针的当前位置为: 23
将文件指针移动到文件开头,文件指针的当前位置为: 0
将文件指针移动到文件末尾,文件指针的当前位置为: 23
将文件指针向后移动 10 个字节,文件指针的当前位置为: 33
chmod 修改文件/目录权限
path = '/home/yt/python/tmp.txt'
os.chmod(path, 0o750) #修改文件/目录权限为750
将原本权限(664)修改为750
--------------------- 文件内容 ---------------------
write 写入内容到文件
path = '/home/yt/python/tmp.txt'
# 打开文件
fd = os.open(path, os.O_RDWR | os.O_CREAT)
# 写入数据(写入的数据必须是 bytes 类型。因此,需要将文本字符串转换为字节数组并进行编码,以便将其写入文件)
os.write(fd, 'Hello \n yt'.encode())
# 关闭文件
os.close(fd)
- 注意:这种方式会直接覆盖原有的数据
如果需要一次写入多个字节数据,可以使用 os.writev()
path = '/home/yt/python/tmp.txt'
# 打开文件
fd = os.open(path, os.O_RDWR | os.O_CREAT)
# 写入多个缓冲区的数据
buffers = [
b'aa\n',
b'bb\n'
b'cc\n'
]
os.writev(fd, buffers)
# 关闭文件
os.close(fd)
- 需要注意的是:这种方式是按照写入字符串的大小对文件本身内容进行替换的。如果文件本身有 "abc" 三个字符,写入了一个字符 "Y",那么仅仅是替换第一个字符,得到 "Ybc"
dup2 将内容覆盖到文件中
# 打开输出文件
with open('tmp.txt', 'w') as f:
# 复制标准输出的描述符
stdout_copy = os.dup(1)
# 将文件描述符复制给标准输出的描述符
os.dup2(f.fileno(), 1)
# 向标准输出打印文本,此时输出将被重定向到文件
print('1 2 3')
# 恢复标准输出的描述符
os.dup2(stdout_copy, 1)
truncate 截取文件大小
语法
os.truncate('文件' , [大小]) #大小单位:byte
例如
>>> path = '/home/yt/python/tmp.txt'
>>> os.truncate(path, 102400) #指定文件大小
>>> print(os.path.getsize(path))
102400
- 如果文件比指定值小,那么自动填充0,直到达到指定大小
- 如果文件比指定值大,那么仅保留指定的大小
--------------------- 创建删除移动 ---------------------
makedirs 创建目录
- makedirs 可以递归创建多层目录,如果存在同名的目录或文件,则异常报错
os.makedirs(
'./xxx' #目录名/路径
mode=0o750 #指定权限(不指定则默认系统权限)
)
存在同名的目录或文件,异常报错
remove 删除文件
- 只能删除文件
os.remove('[文件路径]')
rmdir 删除空目录
os.rmdir('空目录路径')
与 removedirs 不同,rmdir不会递归删除
removedirs 递归删除空目录
os.removedirs('[空目录路径]')
注意:只能删除空目录,也会递归删除。比如创建了几层目录 mkdir ./a/b/c ,那么删除目录c(绝对路径),那么连同a/b都会被删除
rename 移动文件
os.rename('[旧文件]' , '新文件')
注意:不支持目录,移动到新位置也必须指定文件名称
os.rename('/home/tmp.txt' , '/data/tmp.txt')
renames 重命名目录
os.renames('旧名称' , '新名称')
access 判断文件
语法
os.access('[文件路径]', [判断类型])
判断类型:
os.F_OK:检查路径是否存在。
os.R_OK:检查读取路径的权限。
os.W_OK:检查写入路径的权限。
os.X_OK:检查执行路径的权限。
判断文件是否存在
>>> print(os.access('./tmp.py', os.R_OK))
True
5. 获取信息类
--------------------- 系统 ---------------------
uname 获取系统信息
语法
os.uname().[信息类型]
信息类型包括:
sysname:操作系统名称
release:操作系统发行版号
version:操作系统发行版名称
nodename:主机名
machine:计算机类型
举例
# 获取系统信息
>>> info = os.uname()
# 打印系统信息
>>> print(f"系统名称: {info.sysname}")
>>> print(f"系统发行: {info.release}")
>>> print(f"系统版本: {info.version}")
>>> print(f"本机名称: {info.nodename}")
>>> print(f"机器类型: {info.machine}")
系统名称: Linux
系统发行: 3.10.0-1160.90.1.el7.x86_64
系统版本: #1 SMP Thu May 4 15:21:22 UTC 2023
本机名称: localhost.localdomain
机器类型: x86_64
times 获取进程运行时间、cpu时间
语法
os.times().[类型]
类型包括:
user: 进程在用户模式下消耗的CPU时间。
system: 进程在内核模式下消耗的CPU时间。
children_user: 进程所有子进程在用户模式下消耗的CPU时间。
children_system: 进程所有子进程在内核模式下消耗的CPU时间。
elapsed: 自进程启动以来经过的真实时间。
计算当前进程、子进程所占用的资源
start = os.times()
# 执行一个耗时的任务
for i in range(10000000):
k = i*2*3*1
end_time = os.times()
print("用户CPU时间:", end_time .user - start.user)
print("系统CPU时间:", end_time .system - start.system)
print("所有子进程用户CPU时间:", end_time .children_user - start.children_user)
print("所有子进程系统CPU时间:", end_time .children_system - start.children_system)
print("自进程启动以来的耗时(秒):", end_time .elapsed - start.elapsed)
cpu_count 获取CPU核心数
>>> print(os.cpu_count())
8
get_terminal_size 获取终端窗口宽和高
>>> size = os.get_terminal_size()
>>> print('终端的宽为:', size.columns)
>>> print('终端的高为:', size.lines)
终端的宽为: 189
终端的高为: 26
linesep 获取当前系统的换行符
>>> print(repr(os.linesep))
'\n'
--------------------- 文件 ---------------------
lstat 获取文件详细信息
语法
#获取信息
变量 = os.lstat("test.txt")
#输出信息
变量.信息类型
信息类型:
st_mode:文件的模式(权限)。
st_ino:文件的 inode 节点号。
st_dev:文件的设备号。
st_nlink:文件的硬链接数量。
st_uid:文件的所有者的用户 ID。
st_gid:文件的所有者的组 ID。
st_size:文件的大小,以字节为单位。
st_atime:文件的最后访问时间(access time)。
st_mtime:文件的最后修改时间(modify time)。
st_ctime:文件的最后状态改变时间(status change time)。
st_atime_ns:文件的最后访问时间,以纳秒为单位。
st_mtime_ns:文件的最后修改时间,以纳秒为单位。
st_ctime_ns:文件的最后状态改变时间,以纳秒为单位。
st_blocks:文件占用的磁盘块数量,以 512 字节为单位。
st_blksize:文件的磁盘块大小,以字节为单位。
举例
# 获取文件状态信息
stat_info = os.lstat("tmp.txt")
# 打印文件状态信息
print("文件的 inode 节点号为:", stat_info.st_ino)
print("文件的所有者的用户 ID 为:", stat_info.st_uid)
print("文件的所有者的组 ID 为:", stat_info.st_gid)
print("文件大小为:", stat_info.st_size, "字节")
print("文件最后访问时间为:", stat_info.st_atime)
print("文件最后修改时间为:", stat_info.st_mtime)
print("文件最后状态改变时间为:", stat_info.st_ctime)
print("文件最后访问时间为(纳秒):", stat_info.st_atime_ns)
print("文件最后修改时间为(纳秒):", stat_info.st_mtime_ns)
print("文件最后状态改变时间为(纳秒):", stat_info.st_ctime_ns)
print("文件占用的磁盘块数量为:", stat_info.st_blocks, "块")
print("文件的磁盘块大小为:", stat_info.st_blksize, "字节")
fstat 获取文件设备号
语法
os.fstat([文件描述符])
with open('./tmp.txt', 'w') as f: #打开文件
f.write('abc') #写入数据
fd = f.fileno() #获取文件描述符
stat_info = os.fstat(fd) #获取文件设备号
print(stat_info.st_mode) #打印设备号
extsep 获取后缀
>>> file = '/home/yt/aaa.txt'
>>> f_key, f_value = os.path.splitext(file) #分开获取路径的后缀
>>> print('后缀前:', f_key)
>>> print('后缀名:', f_value)
后缀前: /home/yt/aaa
后缀名: .txt
--------------------- 目录 ---------------------
getcwd 获取当前路径
获取执行程序的路径,而不是程序本身的路径
os.getcwd()
listdir 列出目录下的文件/目录
#列出当前目录
print(os.listdir())
#列出指定目录
print(os.listdir('/home/yt'))
scandir 遍历目录树
os.scandir('路径')
举例
with os.scandir('/home/') as f:
for i in f:
print(i)
--------------------- 用户进程 ---------------------
getlogin 获取登录用户名
- 注意:获取的是登录的用户,su 命令切换的用户无效
print(os.getlogin())
getpid 获取当前进程PID
>>> print(os.getpid())
52255
getppid 获取当前进程PPID
>>> print(os.getppid())
52362