Python子流程PIPE中的多个输入(使用stdin或通信)

时间:2014-08-03 09:31:12

标签: python subprocess stdin popen

我一直在寻找上述问题的答案。

Popen命令不应该返回任何内容,它只是要求"你想继续吗?" (是)和"管理员密码"取自本地数据库。

当前的代码状态是:一切正常但是第二个输入,第一个输入通过。

  • 我使用的是Ubuntu服务器(使用Python -u)
  • 在每次stdin.write
  • 之后尝试刷新
  • 尝试沟通(有问题,代码循环无限次)
  • 尝试了pexpect,但也有问题,Popen在我的条件下更适合我猜。

所以,我愿意接受建议并愿意尝试你的帮助。任何帮助将不胜感激。

        #Input 1
        p = Popen(["foo", "bar"], stdin=PIPE, universal_newlines=True)
        try:
            p.stdin.write('yes' + linesep)
        except IOError as e:
            if e.errno == errno.EPIPE or e.errno == errno.EINVAL:
                break
            else:
                raise
        p.stdin.flush()
        #Input 2
        try:
            p.stdin.write(KeyPass + linesep)
        except IOError as e:
            if e.errno == errno.EPIPE or e.errno == errno.EINVAL:
                break
            else:
                raise
        p.stdin.flush()
        p.stdin.close()
        p.wait()

3 个答案:

答案 0 :(得分:1)

  

它不会回复密码,也不会反映星号。

这意味着您无法通过stdin开车。你想要做的就是不可能那样。

查看是否有另一种方法可以给它一个密码 - 可能在命令行上,或通过环境 - 或者为了避免给它一个密码(例如,使用ssh你可以交换密钥而不是传递密码)

如果没有,您唯一的选择是给它一个伪TTY而不是常规管道。 (即使这不能保证有效,但它可能有效,值得一试。)

有三种方法可以从Python执行此操作:os.openptyos.forkptypty模块。从理论上讲,forkpty是特定于平台的,但在实践中,因为pty仅在Linux上进行测试,而openpty要求您执行其他特定于平台的内容以实际执行任何操作对它有用,我从forkpty开始。代码如下所示:

pid, fd = os.forkpty()
if not pid:
    # We're in the child here, but we still have to launch the program
    os.execlp('foo', 'bar')
# This code is still in the parent.

现在,家长可以使用os.read(fd)os.write(fd)与孩子交谈,孩子会将其视为来自TTY。孩子完成后,你必须os.waitpid(pid)。请记住,你在这里处理低级文件I / O-没有解码到Unicode,没有通用换行符,最重要的是,没有缓冲。这可能很难处理,但你必须处理它。

或者,当然,您可以使用像pexpect这样的库,它可以使用PTY并隐藏您的所有详细信息。我不确定为什么你会对这个想法产生抵触情绪,但当你因为试图处理forkpty而感到沮丧时,也许再给它一次机会。

答案 1 :(得分:0)

  

它只是要求“你想继续吗?” (是)和“管理员密码”

如果子进程询问“...继续?”并在出现提示时写入密码,则回答"yes"

import pexpect # $ pip install pexpect

output, status = pexpect.run('foo bar',
    events={r'continue\?': 'yes\n', 'password': 'p4$$W__rd\n'},
    withexitstatus=1)

pexpect确保即使子进程直接向/从终端写入/读取(进程外部进程'stdout / stdin),您也会看到它的输出并接收您的输入。

答案 2 :(得分:0)

您可以使用communicate()代替write()

p.communicate(input='{}\n{}'.format('yes', KeyPass).encode('utf-8'))