Python脚本与linux shell交互

2023-12-27

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

我目前有这个:

# 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

这将执行 shell 命令(例如 adduser newuser02),就像在终端中键入命令一样,包括交互行为。这很好。

现在,我想从 Python 脚本中记录屏幕上出现的所有内容。但我似乎无法使该部分发挥作用。

我尝试过使用 subprocess.PIPE 的各种方法,但这通常会扰乱交互性,例如不输出提示字符串。

我还尝试了各种方法来直接更改 sys.stdout 的行为,但是当子进程直接写入 sys.stdout.fileno() 时,这一切都无济于事。


Popen可能不太适合交互式节目,因为缓冲问题 https://stackoverflow.com/q/20503671/4279并且由于以下事实有些程序直接从终端写入/读取 https://stackoverflow.com/q/20980965/4279例如,检索密码。看问:为什么不直接使用管道(popen())? http://pexpect.readthedocs.org/en/latest/FAQ.html#whynotpipe.

如果你想效仿script utility http://linux.die.net/man/1/script那么你可以使用pty.spawn() http://docs.python.org/2/library/pty.html#pty.spawn,请参阅中的代码示例复制 Python 子进程的终端输出 https://stackoverflow.com/q/20568828/4279 or in 记录 python 子进程的语法错误和未捕获的异常并将其打印到终端 https://stackoverflow.com/q/12508752/4279:

#!/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 http://pexpect.readthedocs.org为了获得更大的灵活性:

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 http://docs.python.org/2/library/subprocess.html:

#!/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,您可以使用teed_call() from Python子进程将子进程的输出获取到文件和终端? https://stackoverflow.com/q/4984428/4279

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python脚本与linux shell交互 的相关文章

随机推荐