子进程和 Python 我做错了啥? [复制]

Posted

技术标签:

【中文标题】子进程和 Python 我做错了啥? [复制]【英文标题】:Subprocess & Python what am I doing wrong? [duplicate]子进程和 Python 我做错了什么? [复制] 【发布时间】:2021-12-03 22:13:44 【问题描述】:

我无法对这个做出正面或反面。尝试在 python 脚本中使用子进程通过iw 抓取我的 wifi 信号。终端命令工作正常:

root@123da06:/app# iw dev wlan0 link | grep signal | awk 'print $2'
-62

但是尝试在 python 中运行时失败:

root@123da06:/app# python3 sub.py
Traceback (most recent call last):
  File "sub.py", line 2, in <module>
    output_bytes = subprocess.check_output("iw dev wlan0 link | grep signal | awk 'print $2'")
  File "/usr/local/lib/python3.8/subprocess.py", line 411, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/local/lib/python3.8/subprocess.py", line 489, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/local/lib/python3.8/subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/local/lib/python3.8/subprocess.py", line 1702, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: "iw dev wlan0 link | grep signal | awk 'print $2'"

脚本再简单不过了:

import subprocess
output_bytes = subprocess.check_output("iw dev wlan0 link | grep signal | awk 'print $2'")
output = output_bytes.decode("utf-8") 
print(f'Signal: output')

我做错了什么?

【问题讨论】:

您可以尝试使用shell=True 选项运行,例如:subprocess.check_output("iw dev wlan0 link | grep signal | awk 'print $2'", shell=True) 即使在 shell 中,也最好将其写为双命令管道:iw dev wlan 0 link | awk '/signal/ print $2'。使用 Python,我也会跳过 awk 并在 Python 本身中处理 iw 的输出。 for line in subprocess.check_output(["iw", "dev", "wlan0", "link"]): .... 【参考方案1】:

您在这里遇到的一件大事是iw dev wlan0 link | grep signal | awk 'print $2' 不是一个进程。

这是三个进程,通过管道连接:iw,其输出通过管道传输到grep,其输出通过管道传输到awk

值得注意的是,当您运行此命令时创建这些管道的是 shell - 很可能是 bash - 它是根据您传递给它的命令执行此操作的。

然而,Python 的子进程命令希望您将可执行文件的路径作为第一个参数传递。然后,您可以传递其他字符串以用作您正在运行的可执行文件的参数。那么,以 python 的方式做事大致如下:subprocess.check_output("/usr/sbin/iw", "dev", "wlan0"...)。这就是 python 感到困惑的原因——你传递给它的大长字符串不是文件路径。

但是,您可以告诉 python 您正在使用一个参数传递给它一个很大的长 shell 命令 - 布尔值 shell arg。

试试这个:

# note the "shell=True" bit
output_bytes = subprocess.check_output("iw dev wlan0 link | grep signal | awk 'print $2'", shell=True)

你应该会看到它成功了。 Python 会接受您的命令并将其交给 shell,后者将正确执行它,而不是尝试使用您传递给它的字符串作为要运行的可执行文件的文件名。

【讨论】:

成功了,谢谢!甚至没有考虑过关于三个独立过程的意义。 我相信我们在知识库中还有其他答案,这些答案不仅描述了此答案中教授的技术,而且描述了如何为每个答案创建单独的 Popen 对象在管道中的阶段并将它们连接在一起,以允许在没有shell=True 的情况下使用管道。

以上是关于子进程和 Python 我做错了啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为 OpenCart 上传数据库后,我收到此错误消息。我做错了啥? [复制]

警告:mysqli_real_escape_string() 需要 2 个参数,1 个给定...我做错了啥? [复制]

警告:mysqli_real_escape_string() 需要 2 个参数,1 个给定...我做错了啥? [复制]

使用`setVariables`后中继生成无效查询-我做错了啥吗?

ARM 汇编语言 uART0 输入输出,我做错了啥。

SQL主键分配错误..不确定我做错了啥? [关闭]