Попен общаться не работает
У меня есть скрипт, который работал должным образом в течение последних 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()
?
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()
См. Как завершить подпроцесс python, запущенный с shell=True