使用subprocess.run和cat命令合并文件时在Linux环境下出现阻塞问题
使用subprocess.run和cat命令合并文件时在Linux环境下出现阻塞问题
嗨,我来帮你分析下问题出在哪:你的代码之所以在Linux下卡住,核心原因是同时混用了shell=True和拆分后的命令列表,这让shell解析命令的方式完全乱套了!
你看,当设置shell=True时,subprocess会启动一个shell进程,需要把完整的命令字符串传给它,让shell自己去拆分参数、处理重定向。但你现在把命令拆成了列表['cat', '/path/a.txt', '/path/b.txt', '>', '/path/c.txt']再传进去,shell会把这个列表当成:用sh -c 'cat'来执行,剩下的/path/a.txt这些都变成了shell自身的参数,而不是cat的参数。
这时候cat因为没收到任何文件名参数,就会默认等着从标准输入读内容,可你的程序又没给它输入,自然就一直卡住不动了!
接下来给你几个解决办法,按推荐程度排序:
1. 最推荐:直接用Python原生代码合并文件(跨平台+无安全隐患)
完全不用依赖系统的cat命令,Windows和Linux都能跑,还能避免路径里有特殊字符(比如空格、&)时的命令解析错误:
import os current_dir = os.getcwd() bottom_file = 'b.txt' top_file = 'a.txt' result_file = 'c.txt' # 用二进制模式处理,兼容文本和二进制文件 with open(os.path.join(current_dir, result_file), 'wb') as out_f: # 先写入top_file的内容 with open(os.path.join(current_dir, top_file), 'rb') as in_f: out_f.write(in_f.read()) # 再追加bottom_file的内容 with open(os.path.join(current_dir, bottom_file), 'rb') as in_f: out_f.write(in_f.read())
2. 修复shell=True的写法
如果你一定要用cat命令,那直接把完整的命令字符串传给subprocess.run,不要拆分:
import os, subprocess current_dir = os.getcwd() bottom_file = 'b.txt' top_file = 'a.txt' result_file = 'c.txt' command_line = f"cat {os.path.join(current_dir, top_file)} {os.path.join(current_dir, bottom_file)} > {os.path.join(current_dir, result_file)}" # 直接传命令字符串,不用split subprocess.run(command_line, shell=True)
不过要注意:如果你的路径里包含空格、*这类shell特殊字符,这种写法还是会出问题,所以更推荐第一种方法。
3. 不用shell=True的subprocess写法
如果想避免shell=True的安全风险(比如路径被注入恶意命令),可以用subprocess的stdout重定向来实现:
import os, subprocess current_dir = os.getcwd() bottom_file = 'b.txt' top_file = 'a.txt' result_file = 'c.txt' with open(os.path.join(current_dir, result_file), 'wb') as out_f: # 执行cat top_file,把输出写到结果文件 subprocess.run( ['cat', os.path.join(current_dir, top_file)], stdout=out_f ) # 再执行cat bottom_file,追加到结果文件 subprocess.run( ['cat', os.path.join(current_dir, bottom_file)], stdout=out_f )
这样调整后,程序就不会再阻塞了,而且能稳定合并文本或二进制文件~
备注:内容来源于stack exchange,提问作者paul18fr




