Appearance
36|系统交互
Python 脚本经常需要与操作系统交互:执行系统命令、读取环境变量、处理命令行参数、操作进程。标准库的 subprocess、os、sys、argparse 提供了这些能力。
一、执行系统命令
subprocess.run() 是执行外部命令的推荐方式:
python
import subprocess
result = subprocess.run(
["ls", "-la"], # 命令和参数用列表传
capture_output=True, # 捕获 stdout 和 stderr
text=True, # 输出按文本处理(不是 bytes)
check=False, # 非零退出码不自动抛异常
)
print(result.returncode) # 0 表示成功
print(result.stdout) # 标准输出
print(result.stderr) # 标准错误capture_output=True 等价于 stdout=subprocess.PIPE, stderr=subprocess.PIPE。
安全警告:不要拼字符串传命令,尤其当命令包含外部输入时:
python
# 危险:命令注入
filename = "; rm -rf /" # 假设来自用户输入
subprocess.run(f"cat {filename}", shell=True)
# Shell 会把这一行解析成:cat ; rm -rf /
# 安全:列表传参
subprocess.run(["cat", filename])
# filename 只是一个字符串参数,不会被当命令执行shell=True 把字符串交给 Shell 解释器解析,有命令注入风险。除非必须使用 Shell 特性(如管道、重定向、通配符),否则不要用 shell=True。
需要 Shell 特性时,用列表传基础命令,Python 处理逻辑:
python
# 不用 shell=True 的管道
p1 = subprocess.Popen(["cat", "data.txt"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", "error"], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close()
output = p2.communicate()[0]二、环境变量
python
import os
# 读取
env = os.environ.get("APP_ENV", "dev") # 没设置时返回默认值 "dev"
api_url = os.environ.get("API_URL") # 没设置时返回 None
# 必填变量集中校验
def require_env(name):
value = os.environ.get(name)
if not value:
raise RuntimeError(f"缺少环境变量: {name}")
return value
token = require_env("API_TOKEN")密码、Token 等敏感信息不要硬编码在代码里。环境变量、配置文件(权限收紧)、密钥管理系统都比硬编码可控。
三、命令行参数
argparse 解析命令行参数,自动生成帮助信息:
python
import argparse
def parse_args():
parser = argparse.ArgumentParser(description="处理数据文件")
parser.add_argument("input", help="输入文件路径")
parser.add_argument("-o", "--output", default="output.txt", help="输出文件路径")
parser.add_argument("-v", "--verbose", action="store_true", help="详细输出")
parser.add_argument("-n", "--count", type=int, default=1, help="处理次数")
return parser.parse_args()
args = parse_args()
print(args.input) # 位置参数
print(args.output) # 可选参数,默认值 output.txt
print(args.verbose) # True 或 False
print(args.count) # 整数,默认 1运行:
bash
python script.py input.txt -o result.txt -v -n 5
python script.py --help # 自动生成帮助四、进程信息
python
import os
os.getpid() # 当前进程 ID
os.getppid() # 父进程 ID
os.getcwd() # 当前工作目录
os.chdir("/tmp") # 切换目录五、临时文件
python
import tempfile
# 创建临时文件
with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f:
f.write("临时数据")
print(f.name) # 临时文件路径
# 创建临时目录
with tempfile.TemporaryDirectory() as tmpdir:
print(tmpdir) # 临时目录路径
# 在 tmpdir 中操作...
# 离开 with 块后自动删除delete=False 表示退出 with 块后不自动删除,方便排查。默认 delete=True。
六、锁文件
防止同一个脚本重复运行:
python
from pathlib import Path
import os
lock_path = Path("/tmp/my_script.lock")
if lock_path.exists():
raise SystemExit(f"锁文件存在: {lock_path}")
try:
lock_path.write_text(str(os.getpid()))
print("执行主逻辑")
finally:
lock_path.unlink(missing_ok=True)这种锁文件适合单机简单场景。跨机器、长任务、异常退出后自动清理这些需求,要换分布式锁或调度系统。
记忆锚点:subprocess.run() 执行命令,列表传参安全,shell=True 有注入风险;环境变量用 os.environ.get() 读取;argparse 解析命令行参数;敏感信息从环境变量读,不要硬编码;tempfile 创建临时文件/目录;锁文件防止重复运行,单机简单场景够用。