Python Forum
[PyQt] How to open a program with python without freezing
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyQt] How to open a program with python without freezing
#1
Hi, can someone tell me how I can open a program with python without it freezing my program? What I am trying to do is create a program with some quick command buttons that allow me to open other programs or files. The problem is that when ever I open a program it freezes my GUI window until I close the opened program. The only fix I have found is to call explorer then use explorer to open the program or file. This works except for one problem. Explorer opens files with the default program that is registered to open the file with, but I want to be able to choose the program that opens the file. For example, I want to edit a .png file in gimp so I don't want to have the .png file open with photo viewer or paint. How would I get it to open with gimp? So to solve the windo freezing problem I created a new thread to open the programs with and that prevents my GUI window from freezing, but when I open a program the thread then freezes and I can't open any more programs until I close the first one. How do I open programs/files without my program freezing?
Reply
#2
Reply
#3
Probably the biggest question is how you are calling the new process. Are you using run(), or Popen()?

Hopefully this will help: https://docs.python.org/3/library/subprocess.html
Reply
#4
I am using PyQt. I have tried to use subprocess.run() and subprocess.call(). From what I understand is that it executes a command, but then waits for it to exit before I can continue and I don't want it to wait. I need it to run the program/file then allow me to also run other commands. A good way to describe what I want to do is basically create a program like the start menu in windows. Here is an example of some code that I tried where I create a new thread for launching programs.
class thread(QtCore.QThread):
    def __init__(self):
        super(thread, self).__init__()
        self.program = ''#path to program
        self.target = ''#path to file for program to open
    def run(self):
        while True:
            print('-')#prints when loop runs. Shows that loop stops after command executed until you close the created process
            if self.Program != '':
                call(r'%s' % self.program)#runs command
                self.program = ''#resets
            time.sleep(0.7)#Prevents CPU use by waiting a short time between runs
If I set the program to 'explorer' then the loop does not freeze, but I can't set a target file if I set the program to 'explorer' because I would have to set the target as the program I want to run so I won't be able to set a target file. Or I use explorer to open a file but It will only open with the default program set to open it.
Reply
#5
Okay first and foremost -- Python is not multiprocessing when using threads due to the GIL and when you call out to Explorer you are bypassing the GIL that said when you create a thread with an endless loop within it you have to tell it to sleep periodically so that you give the processor back to the OS from time to time to handle those other events that get queued up while it is waiting for this process to pause or finish. Likewise this goes for any and all other processes that you might be running they have to "pause" every now and again (note the actual GUI generally does this naturally due to having to wait on User triggered Events to respond to).

However if you actually need multiprocessing from within Python that can be done as well by using python's multiprocessing library but it has its own set of restrictions and such (aka pros/cons)
Reply
#6
(Aug-13-2019, 06:20 PM)Denni Wrote: Okay first and foremost -- Python is not multiprocessing when using threads due to the GIL and when you call out to Explorer you are bypassing the GIL that said when you create a thread with an endless loop within it you have to tell it to sleep periodically so that you give the processor back to the OS from time to time to handle those other events that get queued up while it is waiting for this process to pause or finish. Likewise this goes for any and all other processes that you might be running they have to "pause" every now and again (note the actual GUI generally does this naturally due to having to wait on User triggered Events to respond to).

However if you actually need multiprocessing from within Python that can be done as well by using python's multiprocessing library but it has its own set of restrictions and such (aka pros/cons)
Yes I know. This is not my problem I only created the thread as a test and put it here for an example of code. I could just use a normal loop or put the call function in the same event loop with the GUI.
class window(QtWidgets.QMainWindow):
    def setup(self):#example stuff
	    self.B = QtWidgets.QPushButton(self)
	    self.B.clicked.connect(stuff)

def stuff():
	call(r'%s' % program)#I want to open other programs or files on my computer(Non python files. Ex: minecraft, gimp, videos, music, web pages, folders...)

program = 'C:\ex\ex.exe'#example

app = QtWidgets.QApplication(sys.argv)
w = window()
w.setup()
w.show()
sys.exit(app.exec_())

When this code runs to open the program the GUI window freezes until I close the program that I opened. The above code was just to show that a thread also freezes as well. How can I make my program allow me to open more than one program without having to first close the first one? Using explorer works, but can I add a third argument that will make the targeted program open a targeted file? I am trying to make a quick access program that allows me to click on links to quickly open things like how the windows start menu does.
Reply
#7
Okay it appears you are asking to open another none-python program from within a python program -- as such I think this is what you need:
https://www.pythonforbeginners.com/os/subprocess-for-system-administrators
Or at least a version of that

Otherwise you will need to spin up your own multiprocessor which sounds fairly simple in concept but can be rather complex depending on what you are attempting to do in totality and/or how you want it to communicate or not.

Basically Threads are for spinning off non-Gui oriented tasks and Multiprocessing and/or Subprocessing are for the more Gui oriented or non-python oriented things
Reply
#8
If you use PyQt then you can use QProcess.startDetached

It starts the app as a separate app and does not block your GUI.

cmd = 'C:\ex\ex.exe'
proc = QProcess()
proc.startDetached(cmd)
Reply
#9
subprocess.run() is a blocking call, which returns stdout after the started program exited.
For your task (starting processes) is multiprocessing not needed and not helpful.
Instead of using subprocess.run, use subprocess.Popen which is not a blocking call.
It returns an object, where stdout, stderr and stdin is attached to.

from subprocess import Popen, PIPE


proc = Popen(['ls', '--help'], stdout=PIPE, stderr=PIPE, encoding='utf8', errors='ignore')
# use stdout
# use stderr
# stdin is not connected to the PIPE, this means no access to stdin
# encoding is utf8, which opens stdout, stderr and stdin in text mode.
# error are ignored

# proc.stdout.read() # blocks until the program finishes (EOF)
# proc.stdout.read(10) # blocks until 10 characters are available.
# proc.stdout.readline() # blocks until a line is available
You can also use select to look if data is available.
Handling the streams right with subprocess is not always easy.

If you need to wait for the whole output of the started program and do not want to block, you can start the proc from a Thread.
Attach a queue to the function and put the data into the queue.
On the other side you can use queue.get_nowait() on the queue to not to block.
The use of queue.get_nowait() need to require catching the exception queue.Empty.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#10
Thank you.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [Tkinter] Open a python program from a button Pedroski55 3 4,881 Jul-20-2020, 11:09 PM
Last Post: Pedroski55
  [Tkinter] GUI keeps freezing Fre3k 2 3,557 May-23-2020, 05:41 PM
Last Post: Fre3k
  [Tkinter] How to create a delay for AI without freezing the GUI kom2 8 6,093 May-04-2019, 02:32 PM
Last Post: Yoriz
  Gi module window freezing problem loss 0 2,211 May-05-2018, 04:42 PM
Last Post: loss

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020