Python 3.x 子进程似乎已结束,但未释放文件句柄

Python 3.x 子进程似乎已结束,但未释放文件句柄,python-3.x,subprocess,signing,Python 3.x,Subprocess,Signing,在Windows8、Python3.3下运行,我生成了3个进程,它们应该一个接一个地运行:首先,对一个可执行文件进行签名,其次,使用Inno设置构建一个工具包(它涉及第一步的可执行文件),最后,使用第二步的输出对其进行签名。然而,从一开始,我就得到了一种似乎是竞争条件的情况,在这种情况下,签名工具抱怨它无法对可执行文件进行签名。在我看来,在查找错误代码后,第二个进程(或操作系统)并没有以某种方式释放文件句柄,尽管应该这样做(我使用process.communicate()来确保这一点)。我还怀疑

在Windows8、Python3.3下运行,我生成了3个进程,它们应该一个接一个地运行:首先,对一个可执行文件进行签名,其次,使用Inno设置构建一个工具包(它涉及第一步的可执行文件),最后,使用第二步的输出对其进行签名。然而,从一开始,我就得到了一种似乎是竞争条件的情况,在这种情况下,签名工具抱怨它无法对可执行文件进行签名。在我看来,在查找错误代码后,第二个进程(或操作系统)并没有以某种方式释放文件句柄,尽管应该这样做(我使用process.communicate()来确保这一点)。我还怀疑存在竞争条件,因为使用time.sleep()似乎可以解决问题

第二个进程是否可能以某种方式脱离自身并在后台运行?但如果是这样的话,为什么我仍然可以在日志文件中看到正确登录的操作(例如,第一次Singing输出、构建、第二次签名(无论成功与否))?我从communicate获得输出这一事实是否意味着所有资源(包括文件句柄)都已释放?代码如下:

def do_build():
'''
Prepare the kit.
'''
    global kit_file 
    kit_file = ''.join([OUTPUT_FILENAME, '_', version]) # do not add '.exe', as Inno does it during build
    DESCR = 'Execute Build'
    logf.write(BEGIN + DESCR + SEP2)

    def run_command(c, ex):
        with subprocess.Popen(c, stdout = subprocess.PIPE, stderr = subprocess.PIPE, executable = ex) as proc:  
            stdout_data, stderr_data = proc.communicate()
            logf.write(str(stdout_data, 'cp1252'))   
        if proc.returncode != 0:    # log errors if needed
            logf.write(str(stderr_data, 'cp1252'))
            sys.exit()       

    sign_exe = [SIGNCODE, '-cn', TTT, '-n', KIT_TYPE2.upper(), '-i', URL, '-t', TSURL]
    sign_kit = sign_exe[:]  # make copy
    sign_exe.append(os.sep.join([PDIR, DEPLOYMENT, EXECUTABLE]))  # sign the executable
    run_command(sign_exe, os.sep.join([PDIR, SIGNCODE]))

    compile = [ISCC, ''.join(['/O', OUTPUT_DIR]), ''.join(['/F', kit_file]), os.sep.join([PDIR, ISS_FILE])]   # compile using the ISS script
    run_command(compile, os.sep.join([ISSC_PATH, ISCC]))

    # time.sleep(something) here seems to save the day...

    sign_kit.append(os.sep.join([PDIR, ''.join([kit_file, '.exe'])]))   # sign the kit, don't forget '.exe'
    run_command(sign_kit, os.sep.join([PDIR, SIGNCODE]))
    logf.write(END + DESCR + SEP2)
我正在使用命令行工具InnoSetup 5,iscc.exe,FWIW

对这种行为有何解释?我看到的唯一解决办法是在尝试最后一次签名之前使用os.access(文件,os.W_OK)


我没有运行防病毒软件,也想不到还有什么会干扰签名过程

结果是我在错误的方向上寻找罪犯

经过更多的研究——并且没有发现是什么进程锁定了我的文件(使用process Explorer,直接从我的脚本LockHunter中获得的句柄工具)——我找到了足够的轶事证据,确定Windows Defender是“罪犯”。显然,它在Windows8中集成得非常好,以至于你完全可以忘记它的实时保护模块是在后台运行的。有时,一旦我的文件可执行文件被创建,它就会将其锁定无限长的时间,刚好足以让我随后的签名尝试失败


我为我最初的错误假设道歉。

使用
with
语句对进程执行
等待
,但其(Lib/subprocess.py)仅由GC通过
关闭。也许这就是时间问题。在使用
执行之后,在运行命令的末尾尝试手动执行过程.\u handle.Close()。谢谢你,埃里克森。我一定会检查你的第一个建议;这是有道理的(在本文中,我发现Pyhton也有一个垃圾收集器…)。这将需要一些广泛的测试,但我会回来做相应的报告;请你重新措辞好吗?我不想假设,也许我错过了什么。谢谢你抽出时间。我想这可能就是问题所在。由于这一过程的性质,这不应引起关注。去参加考试,希望在我给你的答案打上正确标记的路上!比我现在的工作要优雅得多(比睡觉稍微好一点)。谢谢你——根据我的测试,你似乎一针见血!你能把它贴出来作为答案吗?这样我就可以投票了?