【问题标题】:Provide called shell script with input in Python在 Python 中提供带有输入的调用 shell 脚本
【发布时间】:2023-12-04 01:23:01
【问题描述】:

我有一个使用各种 Bash shell 脚本的 python 程序。但是,其中一些需要 (y/n) 输入。我知道基于问题编号所需的输入,因此能够自动提供该输入。

在 Python 中有没有办法做到这一点?

作为最后的手段,我可​​以向窗口等发送信号,但我不想这样做。

【问题讨论】:

    标签: python python-3.x subprocess


    【解决方案1】:

    可能最简单的方法是使用pexpect。一个例子(来自维基中的overview):

    import pexpect
    
    child = pexpect.spawn('ftp ftp.openbsd.org')
    child.expect('Name .*: ')
    child.sendline('anonymous')
    child.expect('Password:')
    child.sendline('noah@example.com')
    child.expect('ftp> ')
    child.sendline('cd pub')
    child.expect('ftp> ')
    child.sendline('get ls-lR.gz')
    child.expect('ftp> ')
    child.sendline('bye')
    

    如果你不想使用额外的模块,使用subprocess.Popen 是可行的方法,但它更复杂。首先创建流程。

    import subprocess
    
    script = subprocess.Popen(['script.sh'], stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE, shell=True)
    

    您可以在此处使用shell=True,也可以将shell 名称添加到命令参数中。前者更容易。

    接下来,您需要阅读script.stdout,直到找到您的问题编号。然后你把答案写到script.stdin

    【讨论】:

    • shell=True 被认为是不安全的。
    • 差不多。 使用不受信任的输入是不安全的。但是在这种情况下,将 shell 的名称添加到 args 列表的替代方法同样是不安全的。如果你想运行一个 shell 脚本,你将不得不使用一个 shell...
    • 请注意,一些密码提示会绕过标准输入直接从控制终端读取。在这些情况下,你不能用管道给他们密码,但仍然可以使用 pexpect。
    【解决方案2】:

    使用subprocess.Popen

    from subprocess import Popen, PIPE
    
    
    popen = Popen(command, stdin=PIPE)
    popen.communicate('y')
    

    【讨论】:

    • 这个答案不能以目前的形式工作,因为您还必须从进程的标准输出中读取“问题编号”。
    • 如果是这样,那么必须做讨厌的管道rw。
    最近更新 更多