Posts: 14
Threads: 7
Joined: Feb 2018
Mar-21-2018, 12:50 PM
(This post was last modified: Mar-21-2018, 12:51 PM by ashtona.)
Hello I'm currently working on a GUI tool in python that launches PDF files from an SQL server. Right now I write the binary to a file and then launch it using subprocess Popen, I track the file name and store the actual subprocess object in a list. When the WM_DELETE_WINDOW event is called I iterate over the child processes killing them and then use os.remove to delete the files.
Here is my code. I can launch the PDF files fine but I can't get the files to close, I receive two errors (ProcessLookupError, psutil.NoSuchProcess: psutil.NoSuchProcess process no longer exists). My file also won't delete as the process is still in use.
1 2 3 4 5 6 7 8 9 |
self .window.destroy()
for process in self .processes:
for child in psutil.Process(process.pid).children():
child.kill()
process.kill()
for file in self .saved_files:
os.remove( file )
|
Any help is appreciated thanks.
Posts: 536
Threads: 0
Joined: Feb 2018
Mar-21-2018, 05:00 PM
(This post was last modified: Mar-21-2018, 05:00 PM by woooee.)
How are you getting the subprocess' pids? Note that psutil can only kill a process that is a child of the program. See if the code below prints anything useful and if so try killing the uid's as they are psuitl processes and not subprocesses processes (glad I don't have to try and say that). I use multiprocessing in these types of situations so can post an example using multiprocessing if you can't get subprocess to work.
1 2 3 4 5 |
for each_pid in pids:
p = psutil.Process(each_pid)
p_name = p.name()
uid = p.uids().real
print (p.name, p, uid)
|
Posts: 14
Threads: 7
Joined: Feb 2018
It errors at
p = psutil.Process(process.pid)
I get, psutil.NoSuchProcess: psutil.NoSuchProcess no process found with pid 2500.
I get the pids from the sub process object and append them to a list
1 2 |
doc = Popen( "start /WAIT " + self .SectionList.get(element), shell = True )
self .processes.append(doc)
|
So when the window destruction event is closed I just iterate over them.
If I understand you correctly I shouldn't be using psutil to kill subprocess objects?
If so what is my other option?
Thanks for your feedback, this has been stumping me quite a bit.
Posts: 536
Threads: 0
Joined: Feb 2018
Mar-21-2018, 06:07 PM
(This post was last modified: Mar-21-2018, 06:07 PM by woooee.)
There is something it doesn't like about the pid and I don't know where the pid is coming from. Because we use what we know, I use multiprocessing (example below) because I know multiprocessing works, and because multiprocessing will use multiple cores when available, so try modifying this code to fit you, and see if it works any better, and obviously post back if it doesn't.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import multiprocessing
import os
import psutil
import time
def killtree(pid, including_parent = True ):
parent = psutil.Process(pid)
for child in parent.children(recursive = True ):
print ( "killing child" , child)
child.kill()
if including_parent:
parent.kill()
def print_numbers(spaces):
ctr = 0
for x in range ( 11 ):
ctr + = 1
print ( " " * spaces, ctr)
time.sleep( 0.5 )
pid = os.getpid()
list_of_multis = []
for ctr in range ( 5 ):
list_of_multis.append(multiprocessing.Process(target = print_numbers, args = (ctr,)))
list_of_multis[ - 1 ].start()
time.sleep( 2 )
killtree(pid)
|
And I got so caught up in psutil that I didn't post terminating each process. This is better than psutil because you can join() each process, which allows anything in the background to be cleaned up.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import multiprocessing
import time
def print_numbers(spaces):
ctr = 0
for x in range ( 11 ):
ctr + = 1
print ( " " * spaces, ctr)
time.sleep( 0.5 )
list_of_multis = []
for ctr in range ( 5 ):
list_of_multis.append(multiprocessing.Process(target = print_numbers, args = (ctr,)))
list_of_multis[ - 1 ].start()
time.sleep( 2 )
for process in list_of_multis:
process.terminate()
process.join()
print (process, "terminated" )
|
Posts: 14
Threads: 7
Joined: Feb 2018
Mar-22-2018, 12:40 PM
(This post was last modified: Mar-22-2018, 12:40 PM by ashtona.)
Ok here is the code I have now. I use multiprocessing to launch the pdf, however it's still not closing my file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
def LaunchPDF(filename):
print (filename)
os.startfile(filename)
def QueryShubertFiles( self ):
for element in self .SectionList.curselection():
value = self .Query( "SELECT Data FROM ShubertDocs WHERE Filename = '" + self .SectionList.get(element) + "';" )
if ".JPG" in self .SectionList.get(element):
bio = BytesIO(value[ 0 ][ 0 ])
Image. open (bio).show()
elif ".PDF" in self .SectionList.get(element) or ".pdf" in self .SectionList.get(element):
self .saved_files.append( self .SectionList.get(element))
try :
with open ( self .SectionList.get(element), 'wb' ) as f:
f.write(value[ 0 ][ 0 ])
except :
pass
self .processes.append(multiprocessing.Process(target = LaunchPDF, args = ( self .SectionList.get(element),)))
self .processes[ - 1 ].start()
def on_closing( self ):
self .window.destroy()
time.sleep( 2 )
print ( self .processes)
for process in self .processes:
process.terminate()
process.join()
print (process, "terminated" )
for file in self .saved_files:
os.remove( file )
|
When I print the processes it tells me they are all stopped, then when I attempt to remove the files I receive a process is still being used. The pdf never closes.
Posts: 4,804
Threads: 77
Joined: Jan 2018
Mar-22-2018, 01:32 PM
(This post was last modified: Mar-22-2018, 01:33 PM by Gribouillis.)
Not a windows user here but instead of opening the pdf with os.startfile() , which creates another process out of the reach of your program, you could launch directly a specific pdf viewer with the subprocess module. For example supposing you open pdf files with Acrobat Reader, it could be
1 2 3 |
viewer = shutil.which( 'AcroRd32' )
proc = Popen([viewer, filename])
processes.append(proc)
|
Posts: 14
Threads: 7
Joined: Feb 2018
Thanks for the help. I resolved this issue by adding one line of code, by checking to see if the sub process object is still running using process.poll().
1 2 3 4 5 6 |
for process in self .processes:
if process.poll() = = None :
for child in psutil.Process(process.pid).children():
child.kill()
process.kill()
|
|