Python脚本和linux shell之间的交互

我有一个Python脚本,需要通过命令行与用户进行交互,同时logging输出的内容。

我目前有这样的:

# lots of code popen = subprocess.Popen( args, shell=True, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stdout, executable='/bin/bash') popen.communicate() # more code 

这就像在terminal中inputshell命令一样执行shell命令(例如adduser newuser02),包括交互行为。 这很好。

现在,我想从Python脚本中logging出现在屏幕上的所有内容。 但我似乎无法使这部分工作。

我已经尝试了使用subprocess.PIPE的各种方法,但是这通常会使交互性紊乱,就像不输出提示string一样。

我也尝试过不同的方法来直接改变sys.stdout的行为,但是当subprocess直接写入sys.stdout.fileno()时,这一切都没有用。

Solutions Collecting From Web of "Python脚本和linux shell之间的交互"

由于缓冲问题以及由于某些程序直接从终端写/读,例如检索密码, Popen可能不太适合用于交互式程序。 Q:为什么不使用管道(popen())? 。

如果您想模拟script实用程序,那么您可以使用pty.spawn() ,参见从Python子流程中复制终端输出中的代码示例,或者在python子流程中记录日志语法错误和未捕获异常,并将其打印到终端 :

 #!/usr/bin/env python import os import pty import sys with open('log', 'ab') as file: def read(fd): data = os.read(fd, 1024) file.write(data) file.flush() return data pty.spawn([sys.executable, "test.py"], read) 

或者你可以使用pexpect更多的灵活性:

 import sys import pexpect # $ pip install pexpect with open('log', 'ab') as fout: p = pexpect.spawn("python test.py") p.logfile = fout # or .logfile_read p.interact() 

如果你的子进程没有缓冲它的输出(或者它不干扰交互)并且把它的输出打印到stdout或stderr,那么你可以尝试subprocess

 #!/usr/bin/env python import sys from subprocess import Popen, PIPE, STDOUT with open('log','ab') as file: p = Popen([sys.executable, '-u', 'test.py'], stdout=PIPE, stderr=STDOUT, close_fds=True, bufsize=0) for c in iter(lambda: p.stdout.read(1), ''): for f in [sys.stdout, file]: f.write(c) f.flush() p.stdout.close() rc = p.wait() 

要分别读取stdout / stderr,你可以使用Python子 teed_call() 的输出文件和终端?

这应该工作

 import subprocess f = open('file.txt','w') cmd = ['echo','hello','world'] subprocess.call(cmd, stdout=f)