【发布时间】:2012-02-08 10:09:04
【问题描述】:
所以我的项目结构如下。我有一个樱桃服务器和一个执行某些操作的后端服务器。现在我有一个“主”app.py 文件来处理启动这些进程。它们的开头如下:
SERVER = subprocess.Popen([PYTHON_EXE_PATH, '-m', WEB_SERVER,
'tvb'], shell=False)
BACKEND = subprocess.Popen([PYTHON_EXE_PATH, '-m', 'bin.rpserver'
, cfg.RPC_SERVER_IP, cfg.RPC_SERVER_PORT],
shell=False)
现在,在它们启动后,这些 pid 将存储在一个文件中,因此用户可以运行停止脚本并关闭它们。这些脚本也可以正常工作,基本上是:
def execute_stop():
if os.path.exists(PID_FILE):
pid_file = open(PID_FILE, 'r')
has_processes = False
for pid in pid_file.read().split('\n'):
if len(pid.strip()):
try:
if sys.platform == 'win32':
import ctypes
handle = ctypes.windll.kernel32.OpenProcess(1, False,
int(pid))
ctypes.windll.kernel32.TerminateProcess(handle, -1)
ctypes.windll.kernel32.CloseHandle(handle)
else:
os.kill(int(pid), signal.SIGKILL)
except Exception, _:
has_processes = True
if has_processes:
sys.stdout.write("Some old PIDs were still registered; \
They could not be stopped.")
pid_file.close()
pid_file = open(PID_FILE, "w")
pid_file.close()
现在这个 pid 文件,连同我的记录器文件和其他创建的数据文件都保存在 cfg.STORAGE 中,我还有一个简单的清理程序:
def execute_clean():
"""Remove TVB folder, TVB File DB, and log file."""
try:
if os.path.isdir(cfg.TVB_STORAGE):
shutil.rmtree(cfg.TVB_STORAGE)
except Exception, excep1:
sys.stdout.write("Could not remove storage folder!")
sys.stdout.write(str(excep1))
单独调用时也可以正常工作。但问题是:我的程序中有一个选项允许用户更改某些设置,在这种情况下,整个程序需要重新启动,并且应该重做这些步骤。为此我:
cherrypy.engine.exit()
self.logger.debug("Waiting for Cherrypy to terminate.")
sleep(2)
python_path = cfg().get_python_path()
proc_params = [python_path, '-m', 'bin.app', 'start', 'web', 'backend']
subprocess.Popen(proc_params, shell=False)
所以这将再次基本上执行以下步骤:
execute_stop()
execute_clean()
start both processes again
我无法理解的奇怪之处在于 execute_stop() 工作正常,正如您在末尾看到的那样,PID_FILE 以写入模式打开并关闭以清除内容,但随后立即在execute_clean() 失败后说PID_FILE 被另一个进程锁定。
现在我已经检查并重新检查,每次打开该文件时它都会关闭,我真的不知道该寻找什么了。这仅发生在 Windows 上,我尝试使用依赖项walker 来查看发生了什么,并且似乎当python 进程运行时,dependency walker 看到这些文件的4个引用和2个处理程序,考虑到它们,这很奇怪每次都关闭。我也觉得很奇怪,我可以在'w' 模式下打开文件,但我不能删除它们。
任何可能出错/寻找什么的想法将不胜感激。
编辑
我已经尝试按照建议使用 os.waitpid,但是在这样做时:
os.waitpid(int(pid), 0)
我收到了[Errno 10] No child processes。我也四处阅读,看到有人说在 Windows 上你应该将句柄而不是 pid 传递给 os.waitpid 所以我也用句柄尝试了它,但我得到了相同的结果。那么到那时这个过程应该不再存在了吧?
【问题讨论】:
标签: python windows subprocess