【问题标题】:Python Catching Popen OutputPython 捕捉 Popen 输出
【发布时间】:2013-05-20 13:13:05
【问题描述】:

我的 Python 脚本退出时遇到了一些奇怪的行为,但没有任何错误消息。根据我的调试,它发生在 popen() 调用以将文件 scp 到服务器。

代码是(我不是原作者):

logMessage(LEVEL_INFO, "copyto is " + copyto)
pid = Popen(["scp", "-i", "/root/.ssh/id_rsa", "/usr/gpsw/gpslog" + self.node_addr, copyto], stdout=PIPE)
__s = pid.communicate()[0]
logMessage(LEVEL_INFO, "GPS log SCP complete")

为了调试,我将其增强为:

logMessage(LEVEL_INFO, "copyto is " + copyto)
pid = Popen(["scp", "-i", "/root/.ssh/id_rsa", "/usr/gpsw/gpslog" + self.node_addr, copyto], stdout=PIPE, stderr=PIPE)
out, err = pid.communicate()
if out:
    print "[" + self.node_addr + "] stdout of pid: " + str(out)
if err:
    print "[" + self.node_addr + "] stdout of pid: " + str(err)
print "[" + self.node_addr + "] returncode of pid: " + str(pid.returncode)
logMessage(LEVEL_INFO, "GPS log SCP complete")

这是我的控制台输出: (模式应该是 5dda77, 5dd9fa, 5dda0d 重复。这是基于物理事件)

[5dda77] returncode of pid: 0
[5dd9fa] returncode of pid: 0
[5dda0d] returncode of pid: 0
[5dda77] returncode of pid: 0
[5dd9fa] returncode of pid: 0
[5dda0d] returncode of pid: 0
# (the script exited and I'm back at the prompt)

这是我的日志输出:

INFO copyto is root@192.168.20.1:/usr/scu/datafiles/gpslog5dda77
INFO GPS log SCP complete
INFO copyto is root@192.168.20.1:/usr/scu/datafiles/gpslog5dd9fa
INFO GPS log SCP complete
INFO copyto is root@192.168.20.1:/usr/scu/datafiles/gpslog5dda0d
INFO GPS log SCP complete
INFO copyto is root@192.168.20.1:/usr/scu/datafiles/gpslog5dda77
INFO GPS log SCP complete
INFO copyto is root@192.168.20.1:/usr/scu/datafiles/gpslog5dd9fa
INFO GPS log SCP complete
INFO copyto is root@192.168.20.1:/usr/scu/datafiles/gpslog5dda0d
INFO GPS log SCP complete
INFO copyto is root@192.168.20.1:/usr/scu/datafiles/gpslog5dda77

所以基于日志和输出数据。我相信在 SCP 期间出现了问题,因为 Python 脚本在记录“GPS log SCP complete”之前就崩溃了。有趣的是我在服务器端看到文件被完全复制。所以两个问题:

  1. 我是否错误地使用了 popen?
  2. 为什么我在 stderr 中看不到任何错误消息?

谢谢

编辑: 该脚本应该永远退出。该过程没有“正常退出”。它应该无限期地运行来自服务器的请求,以从可用的 GPS 节点检索数据。

主循环代码为:

stop_flags = 0

... (API for server and GPS nodes to interact with)

def main():

    ... (System initialization)

    while stop_flags == 0:
        # listen for messages
        xmlrpcserver.handle_request()
        comm.poll()
    if stop_flags == STOP_FLAG_RESTART:
        # suppress Pylint warning for reimport of Popen,PIPE
        # pylint: disable-msg=W0404
        from subprocess import Popen, PIPE
        # use this instead of call to suppress output
        pid = Popen(["/etc/init.d/S999snap",
                    "restart"],
                    stdout=PIPE)
        __s = pid.communicate()[0]
    if stop_flags == STOP_FLAG_REBOOT:
        # suppress Pylint warning for reimport of Popen,PIPE
        # pylint: disable-msg=W0404
        from subprocess import Popen, PIPE
        # use this instead of call to suppress output
        pid = Popen(["reboot"],
                    stdout=PIPE)
        __s = pid.communicate()[0]

if __name__ == '__main__':
    main()

【问题讨论】:

  • 您确定要捕获任何标准错误吗?您是否尝试过从 bash 手动运行失败的命令来查看,或者您只是假设那里一定有什么东西?
  • 同时,是什么让您认为它“崩溃”了?有段错误吗?还是异常回溯?最有可能的是,它退出得很好,logMessage 没有显示最后一条消息的唯一原因是它是您编写的一些自定义代码,它从不刷新关闭日志文件。
  • 你怎么知道python崩溃了?你说没有错误信息并且 scp 是成功的,所以我很好奇你为什么认为它崩溃了。
  • 您必须向我们展示一个完整的、正在运行的示例,并尽可能地精简,以便它仍然可以演示问题。您向我们展示的代码显然只运行一次;如果应该让它永远运行的代码不起作用,您必须向我们展示该代码。
  • @ayuelkenbeck:如果这是问题,它不会多次工作然后失败一次,是吗?

标签: python multithreading popen scp stderr


【解决方案1】:

你用Popen就好了。

而且,尽管除非您以其他方式自己测试相同的命令(例如,只需通过 bash 以交互方式运行它们),否则无法确定,但您很可能在 stderr 中看不到任何内容,因为没有任何内容被打印到stderr

它几乎肯定不会崩溃,除非您有段错误、异常回溯或其他一些不相信的理由。您说它成功完成了所有工作,那么您认为它崩溃的原因是什么?

至于最后一条日志消息没有显示……如果您想要一个明确的答案,您必须向我们展示您的自定义 logMessage 代码,但我愿意永远不会成为您的 flushclose 日志文件.

最后,您已将您的问题标记为multithreading,这很容易相关。同样,甚至没有描述你是如何进行线程的,更不用说实际代码了,我们只能猜测,但你可以,例如,在daemon=True 线程中运行此代码,然后退出主线程。

【讨论】:

  • 这个脚本实际上是崩溃的。它没有终止。它的设计是在 GPS 节点可用时永远运行处理它们。而且,它经常在将数据从这些节点之一发送到服务器后崩溃。 Python 脚本退出,并且没有记录或显示错误。但它总是出现在 SCP 命令之后的代码中的这个确切位置,我从来没有从 SCP PID 得到返回码。
  • 首先,“正常退出”并没有崩溃。其次,您希望我们如何调试导致它终止的任何东西,而不会看到不应终止的代码?
猜你喜欢
  • 1970-01-01
  • 2015-09-21
  • 2019-06-01
  • 2014-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
相关资源
最近更新 更多