Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python子流程管道中的多个输入(使用stdin或communicate)_Python_Subprocess_Stdin_Popen - Fatal编程技术网

Python子流程管道中的多个输入(使用stdin或communicate)

Python子流程管道中的多个输入(使用stdin或communicate),python,subprocess,stdin,popen,Python,Subprocess,Stdin,Popen,我一直在寻找上述问题的答案 Popen命令不应返回任何内容,它只是询问“是否要继续?”(是)以及从本地数据库获取的“管理员密码” 当前的代码状态是:一切正常,但要求我进行第二次输入,第一次输入通过 我使用的是Ubuntu服务器(带有Python-u) 尝试在每次标准写入后刷新 尝试通信(有问题,代码循环次数不限) 尝试过pexpect,但也有问题,我想Popen在我的条件下更合适 所以,我愿意接受建议,并愿意尝试你的帮助。任何帮助都将不胜感激 #Input 1

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

Popen命令不应返回任何内容,它只是询问“是否要继续?”(是)以及从本地数据库获取的“管理员密码”

当前的代码状态是:一切正常,但要求我进行第二次输入,第一次输入通过

  • 我使用的是Ubuntu服务器(带有Python-u)
  • 尝试在每次标准写入后刷新
  • 尝试通信(有问题,代码循环次数不限)
  • 尝试过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()
它不回显密码,也不回显星号

这意味着您无法通过
stdin
。你想做的事情是不可能的

查看是否有其他方法可以在命令行或环境中为其提供密码,或避免为其提供密码(例如,使用
ssh
可以交换密钥,而不是传递密码)

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

有三种方法可以从Python和模块中实现这一点。从理论上讲,
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)
it。请记住,这里处理的是低级文件I/O,没有Unicode解码,没有通用换行符,最重要的是,没有缓冲。这可能很难处理,但你必须处理它

当然,您也可以使用像
pexpect
这样的库,它可以使用PTY并隐藏所有细节。我不知道你为什么抵制这个想法,但是当你在尝试处理
forkpty
时感到沮丧时,也许再给它一次机会

它只是询问“您想继续吗?”(是)和“管理员密码”

如果子进程询问“…继续”,则回答
“是”
,并在提示时写入密码:

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),您也可以看到它的输出并接收您的输入。

您可以使用
communicate()
而不是
write()


如果您试图驾驶交互式应用程序,
Popen
并不比
pexpect
更适合您的情况。告诉我们你尝试了什么,出了什么问题;几乎可以肯定,这是一个更简单的修复方法。此外,它要求“从本地数据库获取的“管理员密码”。通常,当程序要求输入密码时,它们要么从TTY而不是stdin读取,要么在stdin不是TTY或无法设置为NOECHO时拒绝继续,要么调用
libpam
或类似程序,而不是自己读取密码。如果在命令行上运行此命令,输入密码时是否会回显?(此外,您没有读取标准输出,因此在发送密码之前没有等待提示,如果它在提示之前丢弃输入,则会破坏它,许多密码输入都会这样做。)即使发送了yes输入,您也看不到任何内容,但它可以工作,您可以尝试其他任何内容,然后它不会要求管理员密码。我也不想看到任何东西,当我的工作完成时,我不会打印输入或输出,我现在正在调试。此外,还使用minidom从XML数据库解析管理员密码。因此,它被设置为KeyPass变量。对不起,我不知道你说的细节。这是一个简单的应用程序,popen应该足够了。同样,当你在命令行上运行应用程序时,它是否会回显密码?如果你在提示符前开始键入,它会忽略你在提示符前键入的任何内容吗?这就像更改*nix系统的密码一样。它不回显密码,也不回显星号。很抱歉在我的第一次评论中出现误解。我应该再次尝试pexpect,然后再回到这个话题。在与pexpect合作几个小时后,我终于成功了。谢谢你,abarnert。它不会工作,否则问题中的代码会工作。密码很可能是直接从终端读取的。请参阅,对于使用Windows的用户,
run()
将不起作用。它依赖于Unix伪终端。从版本4开始,建议使用(这是实验性的)。@AndrewMyers OP使用Ubuntu。在回答问题时,Pexpect根本不支持Windows<如果程序直接从控制台读取密码(getwch/ReadConsole API-Windows模拟使用pty),code>PopenSpawn将不起作用。
p.communicate(input='{}\n{}'.format('yes', KeyPass).encode('utf-8'))