2013-07-15 2 views
1

У меня есть сценарий, который работает исправно в течение последних 3 месяцев. Сервер прошёл в прошлый понедельник, и с тех пор мой скрипт перестает работать. Скрипт висит на coords = p.communicate()[0].split().Popen communication не работает

Вот часть сценария:

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

«Бесконечно ли он« вешает »на' communication() ', т. Е. Подпроцесс просто не выходит (вы должны его контролировать)? «Различные» серверы обычно подразумевают, что многие части среды, в которой работает программа, различны. Возможно, программа (подпроцесс) зависает, потому что она ожидает ввода от stdin. Попробуйте открыть канал для stdin через 'stdin = subprocess.PIPE' и предоставить некоторый вход для подпроцесса (например, новой строки) через' p.communicate ("\ n") '. Если это поможет, мы сможем позже выяснить, что именно вызвало эту разницу. –

+0

Мартино вы правы. проблема с 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 на стандартный вывод, даже если 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

Смежные вопросы