【问题标题】:Interacting with bash through python without terminating通过python与bash交互而不终止
【发布时间】:2020-02-08 10:09:43
【问题描述】:

我正在尝试创建一个与 /bin/bash shell 交互并获取信息或执行命令的进程。我不想关闭进程,因为我想保留状态以供将来交互。

我在SO answer 上尝试了解决方案,但在一次通信后进程终止。

通过pythonsubprocess API,我发现subprocess.check_output() 非常适合这个。但是,类似于Popen.communicate(),这会在执行一次后终止进程。

最后一种似乎可行但不安全并导致死锁的方法是使用Popen.stdin.writePopen.stdout.read。如果未找到 EOF,则读取操作将进入无限等待。

有没有更安全、更简单的方法来实现这一点?

编辑: 我尝试了更多的东西:

import subprocess
import select
import os

process = subprocess.Popen(['/bin/bash'], shell=True, text=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process.stdin.write('export SOMETHING=10000abc\n')
process.stdin.flush()
process.stdin.write('echo $SOMETHING\n')
process.stdin.flush()

r, w, e = select.select([process.stdout], [process.stdin], [], 0)
if process.stdout in r:
  print (os.read(process.stdout.fileno(), 50))
else:
  print ("Nothing to read")

输出总是Nothing to read

【问题讨论】:

  • 你应该使用pexpect
  • 使用readline 而不是read
  • readline() 面临与 read() 相同的问题,它可能导致死锁。到目前为止,我正在考虑在读取操作上添加超时以打破死锁。
  • 问题可能是由于标准输出是管道时 stdio 缓冲造成的。这就是您应该使用pexpect 的原因,它通过使用pty 来解决这个问题。

标签: python bash process subprocess popen


【解决方案1】:

我最终做了以下事情:

import subprocess
import select
import os

process = subprocess.Popen(['/bin/bash'], shell=True, text=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process.stdin.write('export SOMETHING=10000abc\n')
process.stdin.flush()
process.stdin.write('echo $SOMETHING\n')
process.stdin.flush()

r, w, e = select.select([process.stdout], [process.stdin], [], 0.1)
result = ""
while process.stdout in r:
    result += os.read(process.stdout.fileno(), 100).decode("utf-8")
    r, w, e = select.select([process.stdout], [], [], 0.1)
process.kill()
print (result)

【讨论】:

    猜你喜欢
    • 2012-03-29
    • 1970-01-01
    • 2017-07-14
    • 2014-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    相关资源
    最近更新 更多