subprocess.run()调用shell脚本无预期输出问题求解
问题根因
你的代码存在几个直接导致异常的问题:
- 语法错误:脚本路径
/path/script.sh没有用引号包裹为字符串,Python解析阶段就会报语法错误,根本不会执行到子进程调用逻辑。 - 工作目录不匹配:就算补全引号,子进程默认的工作目录是Python进程的启动目录,和你手动在终端执行脚本时所在的目录大概率不一致,你传入的相对路径
text1.txt、text2.txt会找不到,cat命令执行失败。 - 输出读取错误:你设置了
capture_output=True,脚本的所有标准输出、错误输出都会被捕获存入返回对象的属性中,直接print(sp.run(...))只会打印CompletedProcess对象的结构信息,不会输出脚本实际执行的拼接结果;同时check=True会在脚本执行失败时直接抛出异常,错误信息里才会包含找不到文件的提示,你之前没捕获异常也没打印stderr,就会误以为脚本没执行。 - 前置权限问题:如果你的
script.sh没有加可执行权限,调用时会直接报权限拒绝错误。
正确写法
优先用参数列表传参的方式,不要拼接shell命令,避免命令注入风险,同时显式指定工作目录:
import subprocess as sp # 先在终端执行 chmod +x /path/script.sh 给脚本加可执行权限 res = sp.run( # 命令和参数分开传,不要自己拼接字符串 ["/path/script.sh", "text1.txt", "text2.txt"], check=True, text=True, capture_output=True, # 替换成你手动在终端执行脚本时,text1.txt/text2.txt所在的绝对路径 cwd="/home/yourname/your_work_dir" ) # 打印脚本实际输出的拼接内容 print(res.stdout) # 如果执行有问题,先打印stderr看报错 # print(res.stderr)
如果你一定要用shell=True的模式,写法如下,同样需要指定工作目录:
import subprocess as sp res = sp.run( "/path/script.sh text1.txt text2.txt", shell=True, check=True, text=True, capture_output=True, cwd="/home/yourname/your_work_dir" ) print(res.stdout)
调试提示:如果还是不符合预期,先把
capture_output=True暂时去掉,让子进程的输出直接打印到控制台,能第一时间看到是路径错误、权限错误还是参数传错。
内容的提问来源于stack exchange,提问作者Tutu ツ
相关产品推荐
相关产品推荐

