如何在进程终止后等待,直到使用Python在Windows上解锁文件? 问题描述

如何在进程终止后等待,直到使用Python在Windows上解锁文件? 问题描述,python,subprocess,kill-process,Python,Subprocess,Kill Process,我有一个单元测试,它调用一个外部程序并进行一些测试。之后,外部进程被终止,测试尝试清理外部程序创建的文件。但是,如果我在Windows 10上的kill()命令之后直接调用unlink(),我会得到: PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'my.log' 如果在调用unlink()之前我time.sleep(4

我有一个单元测试,它调用一个外部程序并进行一些测试。之后,外部进程被终止,测试尝试清理外部程序创建的文件。但是,如果我在Windows 10上的
kill()
命令之后直接调用
unlink()
,我会得到:

PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'my.log'
如果在调用
unlink()
之前我
time.sleep(4)
,一切正常。
4
是任意选择的,其他时间也可以

MCVE 这个MCVE有两个文件。一个只锁定日志文件的
server.py
和一个调用服务器、杀死服务器并最终尝试删除日志文件的
test\u client.py

测试客户端.py

import pathlib
import subprocess
import sys
import time

# Create test folder
server_path = pathlib.Path('.')
server_path.mkdir(exist_ok=True)

server_file = pathlib.Path('server.py').resolve()

# Start server in test folder
proc = subprocess.Popen([sys.executable, str(server_file)], cwd=server_path)

time.sleep(4)

# Kill server
proc.kill()

# Activate the following line to avoid the PermissionError: [WinError 32] ...
#time.sleep(4)

# Clean up
pathlib.Path('my.log').unlink()
import time
import logging

logging.basicConfig(
    filename='my.log',
    level=logging.DEBUG)

logging.info('I just started my work')

while True:
    time.sleep(1)
server.py

import pathlib
import subprocess
import sys
import time

# Create test folder
server_path = pathlib.Path('.')
server_path.mkdir(exist_ok=True)

server_file = pathlib.Path('server.py').resolve()

# Start server in test folder
proc = subprocess.Popen([sys.executable, str(server_file)], cwd=server_path)

time.sleep(4)

# Kill server
proc.kill()

# Activate the following line to avoid the PermissionError: [WinError 32] ...
#time.sleep(4)

# Clean up
pathlib.Path('my.log').unlink()
import time
import logging

logging.basicConfig(
    filename='my.log',
    level=logging.DEBUG)

logging.info('I just started my work')

while True:
    time.sleep(1)
问题:
  • 有没有办法等待杀戮结束
  • 如果代码不是特定于平台的,则奖励
    • 正确的方法是

      # Kill server
      proc.kill()
      
      # Activate the following line to avoid the PermissionError: [WinError 32] ...
      proc.communicate()
      
      # Clean up
      pathlib.Path('my.log').unlink()
      
      它这样做的原因需要一些文档

      如中所述

      Popen.kill() 杀死孩子。在Posix OSs上,函数将SIGKILL发送给子级。在Windows上kill()是terminate()的别名

      Popen.terminate() 阻止孩子。在Posix OSs上,该方法将SIGTERM发送给子级。在Windows上,调用Win32 API函数TerminateProcess()来停止子进程

      如前所述,在windows中,它正在调用Win32 API。然而,它明确指出

      TerminateProcess是异步的;它启动终止并立即返回。如果需要确保进程已终止,请使用进程句柄调用WaitForSingleObject函数

      因此,
      kill()
      只是简单的“请求停止”。还没有停止。因此,您需要一种方法来“等待”流程结束

      communicate()
      也是为此目的而设计的,如文档中所述

      与进程交互:向stdin发送数据。从stdout和stderr读取数据,直到到达文件末尾等待进程终止

      正确的方法是

      # Kill server
      proc.kill()
      
      # Activate the following line to avoid the PermissionError: [WinError 32] ...
      proc.communicate()
      
      # Clean up
      pathlib.Path('my.log').unlink()
      
      它这样做的原因需要一些文档

      如中所述

      Popen.kill() 杀死孩子。在Posix OSs上,函数将SIGKILL发送给子级。在Windows上kill()是terminate()的别名

      Popen.terminate() 阻止孩子。在Posix OSs上,该方法将SIGTERM发送给子级。在Windows上,调用Win32 API函数TerminateProcess()来停止子进程

      如前所述,在windows中,它正在调用Win32 API。然而,它明确指出

      TerminateProcess是异步的;它启动终止并立即返回。如果需要确保进程已终止,请使用进程句柄调用WaitForSingleObject函数

      因此,
      kill()
      只是简单的“请求停止”。还没有停止。因此,您需要一种方法来“等待”流程结束

      communicate()
      也是为此目的而设计的,如文档中所述

      与进程交互:向stdin发送数据。从stdout和stderr读取数据,直到到达文件末尾等待进程终止


      它是用Win32.api的C编写的
      kill()
      没有如您所想的那样工作,请尝试添加一行
      proc.communicate()
      ,以便在调用
      unlink()
      之前等待进程结束,然后应该可以工作。实际上,在
      proc.kill()
      之后添加
      proc.communicate()
      可以解决问题。是的,这就是我的意思
      proc.kill()
      只要请求取消即可。你需要等待一些方法<代码>通信()用于此。看看我能不能找到一些文档…这是用Win32.api的C编写的
      kill()
      没有如您所想的那样工作,请尝试添加一行
      proc.communicate()
      ,以便在调用
      unlink()
      之前等待进程结束,然后应该可以工作。实际上,在
      proc.kill()
      之后添加
      proc.communicate()
      可以解决问题。是的,这就是我的意思
      proc.kill()
      只要请求取消即可。你需要等待一些方法<代码>通信()用于此。看看我能不能找到这方面的文件。。。