【问题标题】:Python persistent PopenPython 持久化 Popen
【发布时间】:2010-10-09 23:59:42
【问题描述】:

有没有办法在 Popen 的同一个“会话”中进行多次调用?例如,我可以通过它拨打电话,然后再拨打电话,而不必将命令连接成一个长字符串吗?

【问题讨论】:

  • 由于“会话”在这种情况下没有任何意义,您能解释一下您要做什么吗?这个问题很难解析,而且似乎没有多大意义。也许如果你解释一下你的目标是什么,它会有所帮助。

标签: python subprocess popen


【解决方案1】:

假设您希望能够运行 shell 并向其发送多个命令(并读取它们的输出),您似乎可以执行以下操作:

from subprocess import *
p = Popen(['/bin/sh'], shell=False, stdin=PIPE, stdout=PIPE, stderr=PIPE)

之后,例如:

>>> p.stdin.write("cat /etc/motd\n")
>>> p.stdout.readline()
'Welcome to dev-linux.mongo.com.\n'

(当然,您也应该检查stderr,否则请Popen将其与stdout合并)。上面的一个主要问题stdinstdout 管道处于阻塞模式,因此很容易“卡住”,永远等待shell 的输出。虽然我还没有尝试过,但 ActiveState 网站上有一个 recipe 显示了如何解决这个问题。

更新:在查看了相关问题/答案后,看起来使用 Python 的内置 select 模块来查看 stdout 上是否有数据要读取可能会更简单(当然,stderr 也应该这样做),例如:

>>> select.select([p.stdout], [], [], 0)
([<open file '<fdopen>', mode 'rb' at 0x10341690>], [], [])

【讨论】:

  • 实际上,这与在 shell=True 之间连接命令(使用“;”)没有什么不同。据我所知,原始海报的建议是什么。除非需要外壳功能,否则它仍然很糟糕,这尚未显示。有更安全的选择。
  • 可能;这个问题还不清楚。但是,如果您想充当真实用户和 shell 之间的“代理”(出于某种原因),或者根据某些事件定期发送命令等,那么这样做可能会很有用。例如,ActiveState 配方似乎受到了真实用例的启发。
  • 我完全同意,我只是不认为这个建议在这种特殊情况下一定是好的。我想只有提问者知道。
【解决方案2】:

当您使用 popen 时,您不是在“打电话”,而是在运行一个可执行文件并通过 stdin、stdout 和 stderr 与它交谈。如果可执行文件有某种方式来完成工作的“会话”(例如,通过从标准输入读取行),那么,是的,你可以做到。否则,您需要执行多次。

subprocess.Popen (大部分)只是 execvp(3) 的一个包装器

【讨论】:

  • 这个解释了实际概念,而不是提供技术上正确的替代解决方案,这总是好的。
  • @Arafangion:“替代解决方案”会是什么样子?我什至无法弄清楚问题是什么。唯一的答案就是这个——你的概念错了。
【解决方案3】:

例如,我可以通过它拨打电话,然后再拨打电话,而不必将命令连接成一个长字符串吗?

听起来您使用的是 shell=True。不要,除非你需要。而是使用 shell=False(默认值)并传入一个命令/参数列表。

有没有办法在 Popen 的同一个“会话”中进行多次调用?例如,我可以通过它拨打电话,然后再拨打另一个电话,而不必将命令连接成一个长字符串吗?

你有什么理由不能只创建两个 Popen 实例并根据需要等待/通信?这是正常的做法,如果我理解正确的话。

【讨论】:

  • 为什么不使用 shell=True?
  • @DavidDoria 因为它是一种安全责任——如果攻击者可以影响 Popen 的输入,它允许注入代码。 (例如,运行“ls”+ user_input 显然是错误的)。 shell=False 完全避免了这一切,因此安全属性依赖于你在 Popen 中调用的程序,没有额外的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-03
  • 1970-01-01
  • 1970-01-01
  • 2011-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多