【问题标题】:How to pass two values to stdin using subprocess in python如何使用python中的子进程将两个值传递给stdin
【发布时间】:2014-03-18 00:34:08
【问题描述】:

我正在执行一个脚本,该脚本一个接一个地提示输入 2 个值。我想从脚本本身传递值,因为我想自动执行此操作。

使用 subprocess 模块,我可以轻松传递一个值:

suppression_output = subprocess.Popen(cmd_suppression, shell=True,
        stdin= subprocess.PIPE,
        stdout= subprocess.PIPE).communicate('y') [0]

但传递第二个值似乎不起作用。如果我这样做:

suppression_output = subprocess.Popen(cmd_suppression, shell=True,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE).communicate('y/r/npassword')[0]

【问题讨论】:

    标签: python subprocess


    【解决方案1】:

    你应该使用 \n 而不是 /r/n -> 'y\npassword'

    由于你的问题不清楚,我假设你有一个行为有点像这个 python 脚本的程序,我们称之为 script1.py:

    import getpass
    import sys
    firstanswer=raw_input("Do you wish to continue?")
    if firstanswer!="y":
      sys.exit(0)   #leave program
    secondanswer=raw_input("Enter your secret password:\n")
    #secondanswer=getpass.getpass("Enter your secret password:\n")
    print "Password was entered successfully"
    #do useful stuff here...
    print "I should not print it out, but what the heck: "+secondanswer
    

    它要求确认(“y”),然后要求您输入密码。之后它会做一些“有用的事情”,最后打印密码然后退出

    现在要让第二个脚本 script2.py 运行第一个程序,它必须看起来像这样:

    import subprocess
    cmd_suppression="python ./testscript.py"
    process=subprocess.Popen(cmd_suppression,shell=True\
    ,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
    response=process.communicate("y\npassword")
    print response[0]
    

    script2.py 的输出:

    $ python ./script2.py
    Do you wish to continue?Enter your secret password:
    Password was entered successfully
    I should not print it out, but what the heck: password
    

    如果程序使用特殊方法以安全的方式获取密码,即如果它使用我刚刚在 script1.py 中注释掉的行,则很可能会出现问题

    secondanswer=getpass.getpass("Enter your secret password:\n")
    

    这个案例告诉你,通过脚本传递密码可能不是一个好主意。

    还要记住,使用 shell=True 选项调用 subprocess.Popen 通常也是一个坏主意。使用 shell=False 并将命令作为参数列表提供:

    cmd_suppression=["python","./testscript2.py"]
    process=subprocess.Popen(cmd_suppression,shell=False,\
    stdin=subprocess.PIPE,stdout=subprocess.PIPE)
    

    Subprocess 文档中提到了十几次

    【讨论】:

    • 感谢您的解释。我会让我的问题更清楚一点。我有一个 python 脚本,它运行一个提示我两次的命令:抑制节点:? [y/N]: and Enter schen password: 我想在从子进程模块运行脚本时自动响应这些提示。那可能吗?我只能通过通信()传递第一个答案'y'..如何传递第二个答案?
    • 如果您将communicate('y/r/npassword') 更改为communicate('y\npassword') 或者甚至communicate('y\r\npassword') (在视窗)。如果您要提供您收到的错误消息(如果有的话),那将是最有帮助的。我的 script2.py 具有您想要的脚本功能,它在我的机器上运行良好(linux,python 2.7.5+)
    • 它仍然停在第二个提示符处。这是我的代码:pastebin.com/LA2Dcbvv 它有两个提示:抑制节点:? [y/N]: 和 Enter schen 密码: .它自动接受“y”,但提示输入密码(密码是 test123,我在脚本中硬编码)
    • 那么看来程序没有从标准输入获取密码,所以在这里使用子进程将不起作用。这就是我在回答中提到的问题。一个解决方案是改用模块 pexpect。看这个帖子,问题和你的差不多:stackoverflow.com/questions/230845/…
    • pexpect的简单介绍可以看这里:pythonforbeginners.com/systems-programming/…
    【解决方案2】:

    试试os.linesep:

    import os
    from subprocess import Popen, PIPE
    
    p = Popen(args, stdin=PIPE, stdout=PIPE)
    output = p.communicate(os.linesep.join(['the first input', 'the 2nd']))[0]
    rc = p.returncode
    

    在 Python 3.4+ 中,您可以使用 check_output():

    import os
    from subprocess import check_output
    
    input_values = os.linesep.join(['the first input', 'the 2nd']).encode()
    output = check_output(args, input=input_values)
    

    注意:子脚本可能会直接从终端询问密码,而不使用子进程的标准输入/标准输出。在这种情况下,您可能需要pexpectpty 模块。见Q: Why not just use a pipe (popen())?

    import os
    from pexpect import run # $ pip install pexpect
    
    nl = os.linesep
    output, rc = run(command, events={'nodes.*:': 'y'+nl, 'password:': 'test123'+nl},
                     withexitstatus=1)
    

    【讨论】:

    • no..同样的事情..它接受'y'作为第一个提示但在密码处停止..code..pastebin.com/8L4T67d6
    • @user3431143: update your question 并将代码放在哪里。 “同一件事”也没有提供信息。详细描述发生的事情(在您的问题中)。
    • 脚本要求我自动提供 2 个提示:抑制节点:? [y/N]: 和 Enter schen 密码: .它在第一次提示时自动接受“y”,但提示输入密码(密码是 test123,我在脚本中硬编码)
    • @user3431143:不要将相关信息放在 cmets 中。 update your question instead
    • @user3431143:你看到终端上的密码提示还是空白?
    猜你喜欢
    • 2014-06-22
    • 1970-01-01
    • 2023-03-12
    • 2018-07-22
    • 2021-06-13
    • 2021-06-29
    • 2011-11-21
    • 2015-03-07
    • 1970-01-01
    相关资源
    最近更新 更多