2013-07-15 46 views
1

我有一个脚本,在过去3个月里一直正常工作。服务器上周一停止运行,此后我的脚本停止工作。脚本挂在coords = p.communicate()[0].split()Popen通信不起作用

下面是脚本的一部分:

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()吗?

+0

看起来你的TCL脚本是什么挂。修复。 – martineau

+0

它是否'无限'挂在'沟通()',即子流程是否不退出(你应该监视)? “不同的”服务器通常意味着程序运行环境的许多部分都不相同。这可能是(子进程)程序挂起,因为它期望从stdin输入。尝试通过'stdin = subprocess.PIPE'打开一个管道到stdin,并通过'p.communicate(“\ n”)'提供一些输入给子流程(例如换行符)。如果这有帮助,我们可以稍后找出究竟是什么触发了这种差异。 –

+0

Martineau你是对的。 TCL脚本导致了这个问题。我不知道为什么。相同的脚本在过去3个月里一直在正常工作。生病试图找出答案。 – MrGRafael

回答

1

你可能以前没有守护进程运行你的服务器,也就是说,你有功能stdin,stdout,stderr流。要解决,你可以重定向流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在stdout即使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