【问题标题】:Popen communicate is not workingPopen 通信不起作用
【发布时间】:2013-07-15 13:51:31
【问题描述】:

我的脚本在过去 3 个月内一直正常运行。服务器上周一宕机了,从那以后我的脚本就停止工作了。脚本挂在coords = p.communicate()[0].split()

这是脚本的一部分:

class SelectByLatLon(GridSelector):
def __init__(self, from_lat, to_lat, from_lon, to_lon):
self.from_lat = from_lat
self.to_lat = to_lat
self.from_lon = from_lon
self.to_lon = to_lon

def get_selection(self, file):
p = subprocess.Popen(
        [
    os.path.join(module_root, 'bin/points_from_latlon.tcl'), 
    file, 
    str(self.from_lat), str(self.to_lat), str(self.from_lon), str(self.to_lon)
    ],
        stdout = subprocess.PIPE
    )
    coords = p.communicate()[0].split()
    return ZGridSelection(int(coords[0]), int(coords[1]), int(coords[2]), int(coords[3]))   

当我在另一台服务器上运行脚本时,一切正常。 我可以用其他东西代替p.communicate()[0].split() 吗?

【问题讨论】:

  • 看起来你的 tcl 脚本正在挂起。修复它。
  • 它在communicate() 上是否“挂起”无限长,即子进程不会退出(你应该监控它)吗? “不同的”服务器通常意味着程序运行环境的许多部分是不同的。可能是(子进程)程序挂起,因为它需要来自标准输入的输入。尝试通过stdin=subprocess.PIPE 打开到标准输入的管道,并通过p.communicate("\n") 为子进程提供一些输入(例如换行符)。如果这有帮助,我们稍后可以弄清楚究竟是什么触发了这种差异。
  • Martineau 你是对的。 TCL 脚本导致问题。我不知道为什么。在过去的 3 个月中,相同的脚本一直在正常工作。我想弄清楚。

标签: python subprocess popen communicate


【解决方案1】:

您之前可能在没有守护进程的情况下运行您的服务器,即您有功能性的标准输入、标准输出、标准错误流。要解决此问题,您可以将流重定向到子进程的 DEVNULL:

import os
from subprocess import Popen, PIPE

DEVNULL = os.open(os.devnull, os.O_RDWR)
p = Popen(tcl_cmd, stdin=DEVNULL, stdout=PIPE, stderr=DEVNULL, close_fds=True)
os.close(DEVNULL)

.communicate() 可能会在标准输出上等待 EOF,即使 tcl_cmd 已经退出:tcl 脚本可能已经产生了一个继承标准流并且比其父进程寿命更长的子进程。

如果您知道在tcl_cmd 退出后不需要任何标准输出,那么当您检测到tcl_cmd 已完成时,您可以终止整个进程树。

您可能需要start_new_session=True 模拟才能杀死整个进程树:

import os
import signal
from threading import Timer

def kill_tree_on_exit(p):
    p.wait() # wait for tcl_cmd to exit
    os.killpg(p.pid, signal.SIGTERM)

t = Timer(0, kill_tree_on_exit, [p])
t.start()
coords = p.communicate()[0].split()
t.cancel()

How to terminate a python subprocess launched with shell=True

【讨论】:

    猜你喜欢
    • 2015-08-18
    • 2015-11-19
    • 2014-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    相关资源
    最近更新 更多