2013-07-15 81 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