2017-07-18 85 views
1

蟒蛇:3.4关闭杀进程的文件

操作系统:WIN7/win10

我要杀死蟒蛇正在运行的进程,并关闭所有它打开的文件:

for proc in psutil.process_iter(): 
    if proc.name() == 'myprocess.exe': 
     opened = proc.open_files() 
     proc.kill() 
     for i in opened: 
      print(i.path) 
      io.FileIO(i.path).close() 
      print(io.FileIO(i.path).closed) 

不知何故io.IOBase(i.path).close()不起作用。

说明:

这就像我想干掉Microsoft Word中使用python,但它留下的一些文件打开。我也想关闭这些文件。

Microsoft Word仅仅是一个例子。这是一个自编写的python程序。打开的文件是:

  • 字体(.TTF)
  • clr.pyd
  • 和.dll-S

我应该如何关闭这些文件?

+0

我发布了一个答案给你的问题,但我敢打赌你试图解决一个不同的问题。如果你能够描述这个问题,那会很有帮助。 – jszakmeister

+0

我想创建一个autoupdater:杀死一个进程删除所有文件并以相同的顺序复制新文件。如果有一些打开的文件,我无法删除它们。 – picibucor

+0

一般来说,这是一个非常困难的问题,尤其是像Word这样的用户可能会积极做有用的事情的情况。你可能会导致他们失去工作,或以某种有趣的方式破坏他们的文件(因为只有部分数据被写出)。你需要一个更好的策略来让这样的工作做得很好。它远远超出了StackOverflow问题,恕我直言。 – jszakmeister

回答

0

查看with语句语法。有一个简要概述here

+1

这绝对无助于解决问题。关闭另一个进程文件句柄与关闭本地进程中的文件对象非常不同。 – jszakmeister

+0

@jszakmeister那么我似乎误解了这个问题。我的印象是,如果一个文件是由一个使用'with'语法的进程打开的,那么结束该进程(即使是来自不同的进程)也会自动导致文件句柄清理。你是说那不是吗? – DatHydroGuy

+0

在这一点上你是对的,这不是发生在这里的事情。正在终止的进程不是Python进程(在这个例子中是Word)。海报无法控制该过程及其工作原理。因此,这使得你的回应看起来像是在谈论本地进程(即正在寻求终止并关闭另一进程中的文件句柄的进程)。 '带'在这种情况下没有帮助,因为几个原因(其中一些在我上面的回答中概述)。顺便说一句,我没有投票你的答案(别人这样做)。我只是想澄清不同之处。 – jszakmeister

4

您不需要关闭由进程打开的任何文件。做到这一点automatically

终止一个进程有以下结果:

  • 在这个过程中的任何剩余线程被标记为终止。
  • 该进程分配的任何资源都被释放。
  • 所有内核对象都关闭。
  • 进程代码从内存中删除。
  • 进程退出代码已设置。
  • 过程对象被发送信号。

重要的一点是“所有内核对象都关闭”。对于每个打开的文件句柄,都有一个关联的内核对象 - 这实际上是一个句柄,一个从数字到内核对象的映射。当进程退出时,内核将走到后面并关闭所有关联的文件句柄,套接字等。

此外,您的原始方法有一些问题。首先,打开的文件列表只是当时打开的文件的快照。在询问打开的文件列表并杀死进程之间,进程可能已经打开更多,或关闭并删除了很多。其次,Python的3文档说,对于IOBASE构造是不公开的,因此使用这种方式是wrong

类io.IOBase

所有I/O类的抽象基类,作用于字节流。没有公共构造函数。

通常,您会使用类似io.open()这样的路径。这导致了第三个问题。所有你需要的是路径。为了关闭文件,你真的需要处理。这些句柄是特定于流程的。这意味着在一个进程中,0x55​​55AAAA可能对应于“file1.txt”,但在另一个进程中,它可能对应于“file2.txt”,或者可能根本不是文件(可能是套接字或其他)。所以,即使你有内核句柄,我们也没有办法说“在这个其他进程的上下文中关闭这个句柄”。这违反了过程的一些安全目标。另外,这意味着你实际上在这里做的是创建你自己的句柄,以仅仅转向并关闭它(或者在这种情况下,它可能什么都不做,因为对象没有被正确创建)。

因此,如果您遇到文件仍然存在问题,可能问题在于,在尝试完成所需的任何工作之前,该流程并未真正死亡。如果存在进程正在使用的文件,并且您想再次使用,则可能需要等待进程退出才尝试继续。它看起来像你可以使用psutils.wait_procs()来做到这一点。

此外,在Windows上,我发现防病毒工具经常妨碍。他们持有由应用程序访问的开放文件,使得它看起来像一个进程仍然保持着它们,当它实际上是病毒扫描程序正在做它的事情。我记得有一个不得不在Subversion中处理这个问题的例子。该代码仍然存在today。所以你可能需要等一下再试一次。

更新

Microsoft Word中仅仅是一个例子。这是一个自编写的python程序。打开的文件是:

  • 字体(.TTF)
  • clr.pyd
  • 和.dll-S

我应该如何关闭这些文件?

答案是你不需要。只要确保流程已经退出。这不是一个即时操作,所以在杀死它和实际退出它之间还有一段时间,它仍然保留文件句柄。

鉴于您已经写下了被杀死的流程,我认为一种更好的方法是引入一种方法来启动该流程,让其执行工作,然后正常退出。然后使用subprocess.run()运行该脚本并等待它退出。

2

这就像我想用python杀死Microsoft Word一样,但是它留下了一些打开的文件。我也想关闭这些文件。

这里有一些误解。当你用kill终止Word时,所有的文件都是从系统的角度关闭的,但是它们会被肮脏的关闭。当Word正常终止时,它会刷新其内部缓冲区,删除所有临时文件并将文件标记为clean。当它崩溃或被无情地终止时,所有的清洁都不会发生。某些修改可能不会写入磁盘,并且临时文件仍然存在,因此在下次执行时,Word会警告您文件尚未有序关闭并且必须进行修复。

所以,你不想杀微软的Word,而是接近它,这意味着发布WM_QUIT消息的主窗口。不幸的是,Python中并没有干净利落的支持。有一个关闭Excel的例子,win32com模块here。 Word的转换应该是(当心未经测试):

wd = win32com.client.Dispatch("Word.Application") 
wd.Quit() #quit word, as if user hit the close button/clicked file->exit.