【问题标题】:python script fails running as a daemon (EOFError: EOF when reading a line)python脚本作为守护进程运行失败(EOFError:读取一行时的EOF)
【发布时间】:2019-03-22 11:46:18
【问题描述】:

我创建了一个在命令行上运行良好的 python3 脚本,但是当我尝试在 MacosX 中作为守护程序运行时,会出现错误“EOFError: EOF when reading a line”。基本代码如下:

  (...)

  def main():

    # Connect
    port, speed = connect_port()

    device = XBeeDevice(port, speed)

    try:
      device.open()
      # print("Waiting for data...\n")

     (...)

      device.add_packet_received_callback(packet_received_callback)
      input()

    finally:
      if device is not None and device.is_open():
        device.close()

  if __name__ == '__main__':
    main()

plist 似乎很好,因为脚本启动并运行一次之前会给出错误:

Traceback (most recent call last):
File "/maslestorres.cat/jardiNet_datalogger.py", line 214, in <module>
main()
File "/maslestorres.cat/jardiNet_datalogger.py", line 206, in main
input()
EOFError: EOF when reading a line

所以基本上我不知道如何调整 input() 行以允许作为守护程序运行。 Python 是 3.7.2 版本,MacOSX 是 10.8.5。

【问题讨论】:

  • 请详细说明您在做什么。 input() 在您的代码中的用途是什么?是否等待用户批准才能恢复运行?通常,守护进程的全部意义在于无需用户交互即可连续运行。
  • input() 函数只是为了确保 main 永远不会结束并执行回调。使用繁忙的等待循环可以获得类似的行为 --> while True: pass 但显然这个循环会浪费 CPU
  • 我是否理解正确,您希望您的守护进程到device.open() 一次,然后无限期地等待数据包,在每个数据包上运行packet_received_callback

标签: python python-3.x macos launchd


【解决方案1】:

就其本质而言,守护进程不能从控制台input()。您需要另一种方法来无限期挂起主线程,同时让 XBee PacketListener thread 继续运行回调。

完成此操作的最简单方法是将input() 替换为:

while True:
    time.sleep(1000000)    # arbitrarily large number

当需要关闭时,您系统的服务管理器将停止您的守护进程:

  • 要么发送SIGTERM — 在这种情况下,您的守护程序将立即终止,而不执行finally 块;
  • 或发送SIGINT — 在这种情况下,KeyboardInterrupt 异常将从time.sleep(1000000) 中冒出,finally 块将运行。

在任何一种情况下,您的进程都应该快速停止。

对于更正确的解决方案,也能够优雅地处理SIGTERM,请参见此处:https://stackoverflow.com/a/46346184/200445

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-03
    • 2013-10-14
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 2023-03-02
    相关资源
    最近更新 更多