我有一个过去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()
吗?
答案 0 :(得分: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()
已经退出, tcl_cmd
也可能在stdout上等待EOF:tcl脚本可能产生了一个子进程,该进程继承了标准流并且比其父进程寿命更长。
如果您知道在tcl_cmd
退出后不需要任何标准输出,那么当您检测到tcl_cmd
已完成时,您可以终止整个过程树。
您可能需要start_new_session=True
analog才能杀死整个进程树:
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