如何使用Popen.communicate向需双行输入的外部程序传入两个参数
报错原因
subprocess.Popen.communicate()的参数签名是communicate(input=None, timeout=None),仅接收两个可选参数:第一个是要写入子进程标准输入的内容,第二个是等待超时的秒数(浮点类型)。你之前传入的第二个rna2.encode()会被自动识别为timeout参数,传入bytes类型的值后,内部做超时计算时触发了类型不匹配的错误,这就是你看到TypeError: unsupported operand type(s) for +: 'float' and 'bytes'的根本原因。RNAduplex.exe的交互逻辑是从标准输入逐行读取序列,命令行下需要分行输入两个序列,本质是识别输入流里被换行符分隔的文本,完全可以通过把两个序列用换行符拼接成一段完整输入的方式适配。
修正后的代码实现
按照程序的输入要求,把两个序列用换行符拼接成单段内容,编码后传给communicate()即可,参考代码:
import os import subprocess from subprocess import PIPE rna1 = "GCGCUUCGCCGCGCGCC" rna2 = "GCGCUUCGCCGCGCGCA" # 用换行符拼接两个序列,匹配程序逐行读取的要求 input_seq = f"{rna1}\n{rna2}" p = subprocess.Popen( "RNAduplex.exe", stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True, env={ # 不要直接覆盖系统原有PATH,否则会导致系统命令路径找不到 "PATH": f"D:\\ViennaRNAPackage;{os.environ.get('PATH', '')}" } ) # 仅将拼接完成的单段内容作为第一个input参数传入 stdout_data, stderr_data = p.communicate(input_seq.encode()) print("程序输出:", stdout_data.decode()) print("错误信息:", stderr_data.decode())
实操注意事项
- 不要拆分多次调用
communicate(),也不要手动操作p.stdin写入内容,这类写法很容易造成子进程死锁,communicate()本身的设计就是一次性完成全量输入写入、全量输出回收的安全交互逻辑。 - 如果Windows环境下程序识别不了换行,可以把拼接的
\n换成Windows控制台标准的\r\n换行符。 - 原代码没有捕获标准错误流,一旦
RNAduplex.exe运行时报错,你只会拿到空的标准输出,加上stderr=PIPE后,就能在返回结果里拿到具体的错误提示,降低排查难度。
内容的提问来源于stack exchange,提问作者Little
相关产品推荐
相关产品推荐

