python subprocess communicate() 阻塞

17 投票
3 回答
29277 浏览
提问于 2025-04-15 18:26

我正在使用 subprocess 模块来调用一个外部程序(plink.exe)以登录到服务器;但是当我调用 communicate 来读取输出时,它会被阻塞。下面是我的代码:

 import subprocess
 process = subprocess.Popen('plink.exe hello@10.120.139.170 -pw 123456'.split(), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 print process.communicate() #block here

我知道阻塞的原因是因为 plink.exe 还在运行;但是我需要在这个子进程结束之前读取输出。有没有办法做到这一点呢?

3 个回答

-1

我遇到过类似的情况,当时我需要执行一个命令 lmstat -a,然后获取终端的输出。

如果你只需要运行一个命令,然后读取输出,可以使用以下代码:

import subprocess

Username = 'your_username'
Password = 'your_password'
IP = 'IP_of_system'
Connection_type = '-ssh' #can have values -ssh -telnet -rlogin -raw -serial

p = subprocess.Popen(['plink', Connection_type, '-l', Username, '-pw', Password, IP], \
                     shell = False, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, err = p.communicate('lmstat -a\nexit\n'.encode())
print(out.decode())
0

可能是因为“plink.exe”需要输入参数,如果你不提供这些参数,它会一直等待,直到你输入数据。你可以试着在方法 communicate(input) 中添加一些参数。

32

communicate 方法的主要作用是等待一个进程完成,并把所有的输出结果返回。如果你不想等这个进程结束,就不要调用 communicate。你可以直接从 stdoutstderr 属性中读取输出。

如果这个进程同时向 stdoutstderr 输出内容(而你想分别读取这两部分),你需要小心,确保能同时从这两个地方读取,而不会造成阻塞,否则可能会出现死锁的情况。在 Windows 系统上,这个操作比较复杂,你可能会想用 pexpect 模块来处理。

撰写回答