【问题标题】:Print Subprocess.Popen打印子进程.Popen
【发布时间】:2018-03-19 20:10:38
【问题描述】:

我对函数 Popen 有疑问。我尝试从我使用的命令中检索输出。

print(subprocess.Popen("dig -x 156.17.86.3 +short", shell=True, stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip())

这部分工作,但是当我在 Popen 中调用变量时(用于 IP 中的地址)

print(subprocess.Popen("dig -x ",Adres," +short", shell=True, stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip())

发生了这样的事情:

raise TypeError("bufsize must be an integer")

我认为这是命令的问题,所以我使用了这个解决方案:

command=['dig','-x',str(Adres),'+short']
        print(subprocess.Popen(command, shell=True, stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip())

但现在返回值与控制台不同:

dig -x 156.17.4.20 +short
vpn.ii.uni.wroc.pl.

如何在脚本中打印上述名称? 非常感谢

【问题讨论】:

  • 不同如何?您的前 2 次尝试不起作用,因为您将参数作为 Popen 的参数传递。您的第三次尝试是最接近的尝试,但请告诉我们输出(通过打印 communicate 输出,您将输出和错误流打印为元组和字节。这是您的问题吗?
  • 我期望的输出是来自命令的输出,第三次尝试脚本打印错误的服务器(就像没有看到 IpAdress)
  • 第三个仍然是错误的,因为你传递了一个列表但使用了shell=True。看我的回答;用 cmets 解释一切太难了。

标签: python subprocess stdout


【解决方案1】:

错误是您没有传递单个字符串,而是多个单独的参数:

subprocess.Popen("dig -x ",Adres," +short", shell=True, stdout=subprocess.PIPE)

如果您查看the Popen constructor in the docs,这意味着您将"dig -x" 作为args 字符串传递,将Adres 作为bufsize 传递,并将"+short" 作为executable 传递。这绝对不是你想要的。

您可以通过使用连接或字符串格式构建字符串来解决此问题:

subprocess.Popen("dig -x " + str(Adres) + " +short", shell=True, stdout=subprocess.PIPE)
subprocess.Popen(f"dig -x {Adres} +short", shell=True, stdout=subprocess.PIPE)

但是,更好的解决方法是在此处不使用 shell,并将参数作为列表传递:

subprocess.Popen(['dig', '-x', Adres, '+short'], stdout=subprocess.PIPE)

请注意,如果您这样做,您必须删除shell=True,否则这将不起作用。 (它可能实际上可以在 Windows 上工作,但不能在 *nix 上工作,即使在 Windows 上你也不应该这样做。)在你问题的编辑版本中,你没有这样做,所以它是还是错了。

虽然我们正在这样做,但如果这就是你所做的一切,你真的不需要用它创建 Popen 对象和 communicate。一个更简单的解决方案是:

print(subprocess.run(['dig', '-x', Adres, '+short'], stdout=subprocess.PIPE).stdout.decode('utf-8'))

此外,如果您在调试像您这样的复杂表达式时遇到问题,将其分解成可以单独调试的单独部分确实很有帮助(使用额外的 prints 或调试器断点):

proc = subprocess.run(['dig', '-x', Adres, '+short'], stdout=subprocess.PIPE)
result = proc.stdout.decode('utf-8')
print(result)

这本质上是一样的,效率几乎相同,但更易于阅读和调试。

当我使用 Adres = '156.17.4.20' 运行此程序时,我得到的正是您正在寻找的输出:

vpn.ii.uni.wroc.pl.

【讨论】:

  • 我看到它的工作,但我有 IP 地址列表(如 156.17.4.0/24)并且我使用 nettadr。我必须将此掩码中的所有 IP 放入脚本中,并且在错误中我遇到了这个问题TypeError: Can't convert 'IPAddress' object to str implicitly
  • @Gracjan 然后使用str(Adres) 代替Adres
  • 使用和print(result) 打印空行(没有错误??)
  • 我修好了。我明确声明了 IP 范围和工作 :) 非常感谢 :D
  • 如何使用 |子进程中的 grep ?示例:head = subprocess.run(['HEAD',str_IP,'|','grep','Server'], stdout=subprocess.PIPE) 返回与head = subprocess.run(['HEAD',str_IP], stdout=subprocess.PIPE) 相同的内容。我该如何解决这个问题?因为在控制台中该命令显示:Server: Apache/2.4.6 (Unix) OpenSSL/1.0.1t PHP/5.5.3 。在 Python 中我不能使用这个 grep
猜你喜欢
  • 2017-09-25
  • 1970-01-01
  • 2015-03-22
  • 2015-05-02
  • 2018-12-05
  • 1970-01-01
  • 2014-03-28
  • 1970-01-01
  • 2016-05-09
相关资源
最近更新 更多