1

python: 3.4

OS: win7 / win10

I want to kill a running process with python and close all the files it opened:

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)

Somehow io.IOBase(i.path).close() does not work.

Explanation:

It's like I would like to kill Microsoft Word with python, but it leaves some files open. And I would like to close those files as well.

Microsoft Word is just an example. It is a self-written python programm. The opened files are:

  • fonts (.ttf)
  • clr.pyd
  • and .dll-s

How should I close these files?

11
  • I posted an answer to your question, but I bet you're trying to solve a different problem. It'd be helpful if you could describe that problem instead. Commented Jul 18, 2017 at 9:09
  • I would like to make an autoupdater: killing a process delete all the files and copy the new files in the same order. If there are some opened files, I cannot remve them.
    – picibucor
    Commented Jul 18, 2017 at 9:29
  • In general, that's a really hard problem, especially with something like Word where the user may actively be doing useful things. You could cause them to lose work, or corrupt their file in some interesting way (because only part of the data was written out). You'll need a far better strategy to make something like that work well. It's way beyond a StackOverflow question, IMHO. Commented Jul 18, 2017 at 9:32
  • I responded before the rest of your message made it on... Commented Jul 18, 2017 at 9:33
  • So, you're trying to launch Word, have it do something, and then exit? Either way, you still need to coordinate with Word. Otherwise you potentially kill it before it's done. Perhaps a better way would be to look at mechanisms to automate Word. It could then do the work and exit gracefully instead, which removes a lot of headaches. Commented Jul 18, 2017 at 9:35

3 Answers 3

4

You don't need to close any files that were opened by the process. That is done automatically:

Terminating a process has the following results:

  • Any remaining threads in the process are marked for termination.
  • Any resources allocated by the process are freed.
  • All kernel objects are closed.
  • The process code is removed from memory.
  • The process exit code is set.
  • The process object is signaled.

The important bit is "All kernel objects are closed." For every open file handle, there is an associated kernel object--that's actually what a handle is, a mapping from a number to a kernel object. When the process exits, the kernel will walk behind and close all associated file handles, sockets, etc.

Additionally, you're original approach has a few problems. First, the list of open files is only a snapshot of which ones were open at that time. In between asking for the list of open files and killing the process, the process could have opened many more, or closed and removed many as well. Second, the Python 3 docs say that the constructor for IOBase isn't public, so using it in this way is wrong:

class io.IOBase

The abstract base class for all I/O classes, acting on streams of bytes. There is no public constructor.

Generally, you'd use something like io.open() which takes the path. This leads to the third issue. All you have to work with is the path. In order to close a file, you really need the handle. Those handles are process-specific. This means in one process, 0x5555AAAA may correspond to "file1.txt", but in another process, it might correspond to "file2.txt" or maybe not even a file at all (it could be a socket or something else). So even if you have the kernel handle, we don't really have a way of saying "close this handle in the context of this other process." That violates some security goals of processes. Also, it means that what you're actually doing here is creating your own handle to only turn around and close it (or in this case, it possibly does nothing at all since the object wasn't created correctly).

So, if you're having a problem with files still being held, perhaps the problem is that the process didn't actually die yet before trying whatever work you needed to get done. You may need to wait for the process to exit before attempting to move on if there are files the process was using that you want to use again. It looks like you can use psutils.wait_procs() to do that.

Also, on Windows I find that anti-virus tools often get in the way. They hold open files accessed by applications making it look like a process is still holding onto them when it's actually the virus scanner doing its thing. I remember one instance of having to deal with this in Subversion. The code still exists today. So you might need to simply wait a bit and try again.

Update

Microsoft Word is just an example. It is a self-written python programm. The opened files are:

  • fonts (.ttf)
  • clr.pyd
  • and .dll-s

How should I close these files?

The answer is that you shouldn't need to. Just make sure the process has actually exited. It's not an instantaneous operation, so there's some time between killing it and it actually exiting that it still retains the file handles.

Given that you've actually written the process being killed, I think a far better approach would be to introduce a way to launch that process, have it do its work, then exit gracefully. Then use subprocess.run() to run the script and wait for it to exit.

2

It's like I would like to kill Microsoft Word with python, but it leaves some files open. And I would like to close those files as well.

There is some misunderstanding here. When you terminate Word with kill, all files are closed from a system point of view, but they will be dirty closed. When Word terminates normally, it flushes its internal buffers, removes any temporary files and mark the files as clean. When it crashes or is abruptely terminated, all that cleaning does not occur. Some modifications may not be written to disk, and temp files are still there, so on next execution, Word will warn you that the files have not been orderly closed and have to be repaired.

So you do not want to kill Microsoft Word, but to close it, meaning posting a WM_QUIT message to its main window. Unfortunately, there is no clean and neat support in Python for that. There is an example of closing Excel by the win32com module here. The convertion for Word should be (beware untested):

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

Take a look at the with statement syntax. There's a brief overview here

4
  • 1
    This will definitely not help with the problem. Closing another processes file handles is very different than closing file objects in your local process. Commented Jul 18, 2017 at 9:51
  • @jszakmeister then it seems I've misunderstood the question. I was under the impression that if a file was opened by a process using the with syntax, then ending that process (even from a different process) would automatically cause the file handle cleanup. Are you saying that isn't so? Commented Jul 18, 2017 at 11:09
  • You're right on that point, it's just not what is happening here. The process being terminated is not a Python process (it was Word, in this example). The poster has no control over that process and how it works. So, that makes you response seem like you're talking about the local process (the one looking to terminate and close file handles in the other process). with does not help in this case for several reason (some of which are outlined in my answer above). BTW, I didn't down vote your answer (someone else did that). I just wanted to clarify the difference. Commented Jul 18, 2017 at 11:29
  • @jszakmeister I see your point. Thanks for clarifying. And no worries about the down vote - they're a part of life on SO, and it's understandable given my misunderstanding about the original question. Commented Jul 18, 2017 at 12:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.