Windows上的文件权限的奇怪情况

时间:2012-02-08 10:09:05

标签: python windows subprocess

所以我的项目结构如下。我有一个cherrypy服务器和一个执行某些操作的后端服务器。现在我有一个'main'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进程正在运行时,依赖者walker会看到4个引用和2个处理程序到这些文件,这很奇怪,考虑到它们每次都关闭。我也觉得很奇怪,我可以在'w'模式下打开文件,但我无法删除它们。

任何可能错误/想要寻找的想法都会非常感激。

修改

我尝试过使用#{1}},但在做的时候:

os.waitpid

我得到了 os.waitpid(int(pid), 0) 。我也读过并看到有人说在Windows上你应该将句柄而不是pid传递给os.waitpid所以我也用手柄尝试了但是我得到了相同的结果。那么那个过程应该不再存在了吗?

1 个答案:

答案 0 :(得分:0)

这只是在黑暗中拍摄的...... 我的预感是SERVER,BACKEND进程中的一个或两个没有按预期终止并且具有打开的PID_FILE。检查它们是否各自用mode='a'打开PID_FILE并立即关闭它。除非我以SERVER / BACKEND处理PID_FILE的方式偏离基础,否则在致电os.waitpid(pid)后您也可以尝试TerminateProcess。这应该阻止,直到该过程真正终止。