【问题标题】:subprocess for non-default shell command非默认 shell 命令的子进程
【发布时间】:2017-11-27 15:17:33
【问题描述】:

我在使用子进程时遇到问题。这是我想做的:使用python打开一个shell,然后调用“bluetoothctl”(来自bluez),然后在“bluez”程序下发送/读取其他命令,如“help”。但是,问题是系统不知道“帮助”命令,因为默认情况下 shell 不支持它。它由“bluez”支持。

我的代码:

import subprocess as sub
cmd_line = 'bluetoothctl'
cmd2 = 'help'

open_blue = sub.Popen(cmd_line, shell=True, stdout=sub.PIPE, stderr=sub.STDOUT)
out = open_blue.communicate()[0]
print (out)

open_blue = sub.Popen(cmd2, stdout=sub.PIPE, stderr=sub.STDOUT)
out = open_blue.communicate()[0]
print (out)

错误说:No such file or directory: 'help'

我想知道这里出了什么问题。 谢谢。

【问题讨论】:

    标签: python linux shell subprocess


    【解决方案1】:

    bluetoothctl 读取命令并写入响应。因此,您不应创建尝试执行help 的新进程,而应将其写入bluetoothctl 进程的标准输入。

    我没有此命令可用,但这里有一个完整的、独立的示例,带有 python 本身,它也接受“帮助”命令:

    import subprocess as sub
    
    p = sub.Popen(["python", "-i"], stdin=sub.PIPE, stdout=sub.PIPE);
    print("The process said: " + p.communicate("help")[0])
    

    执行时,你会得到 python 提示符,然后是这个:

    The process said: Type help() for interactive help, or help(object) for help about object.
    

    这正是您在 python -i 提示符中输入 help 时所得到的结果。

    【讨论】:

    • 我想知道 ["python", "-i"],"-i" 在这里做什么?
    • 它使 Python 启动它的 REPL,即使它从管道而不是终端获取数据。没有它,它将读取脚本而不是 repl 命令。比较echo help | pythonecho help | python -i
    【解决方案2】:

    我手头没有 BlueZ 堆栈。进行测试,但前提是它适用于常规 STDOUT/STDIN,您也可以通过管道传输 STDIN,并使用 Popen.communicate() 发送您的命令:

    import subprocess
    
    open_blue = subprocess.Popen(["bluetoothctl"], shell=True, stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
    out, err = open_blue.communicate("help")
    print(out)
    

    但是如果bluetoothctl 期望连续流(即充当子shell),那么communicate() 可能不是正确的方法,因为它基本上等待子进程完成向STDOUT 发送数据,然后将您的命令发送到STDIN 并关闭它,然后等待 STDOUT/STDERR 并关闭它们——有效地使它对向您的子进程发送单个命令有用。如果您要向bluetoothctl 进程发出各种命令,您可能必须为它编写自己的处理程序。适合的东西: 导入子流程

    open_blue = subprocess.Popen(["bluetoothctl"], shell=True, stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
    
    while True:  # lets wait for 'user' prompt
        line = open_blue.stdout.readline().rstrip()
        if line.endswith("#"):  # this is the prompt, presumably, so stop reading STDOUT
            break
        print(line + "\n")  # print the subprocesses STDOUT
    
    open_blue.stdin.write("help\n")  # send the `help` command
    
    while True:  # lets repeat the above process
        line = open_blue.stdout.readline().rstrip()
        if line.endswith("#"):  # this is the prompt, presumably, so stop reading STDOUT
            break
        print(line + "\n")  # print the subprocesses STDOUT
    
    # now you can issue another command... and so on.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-23
      • 2012-05-22
      • 1970-01-01
      相关资源
      最近更新 更多