How to show program on the screen if it was opened? - python

I have a problem with how to show a program window if it was opened
how I open it is using
import os
os.startfile('path/to/progarm.exe')
But if progarm.exe is opened and I forgot to close
when I run that script again, A program.exe doesn't show on the
screen when I was on another window.
So which script can show up the opened program?

The main reason is that your script lost the focus the opened programs windows.
You can control windows with parameters.
os.startfile(path[, operation][, arguments][, cwd][, show_cmd])
also, you can check detail information here.
https://docs.python.org/3/library/os.html#os.startfile

To do what you want, you need to provide the path to the program in your machine.
import os
ms_word = r"C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE"
os.startfile(ms_word)

I would not recommend doing what you are doing the way you are doing it.
Python has a subprocess module to do things like these, with functions specifically designed to do what you are doing. The easiest way to do what you are trying to do is to use the subprocess.runfunction.
import subprocess
subprocess.run(['path/to/app.exe', 'param1', 'param2'..], shell=True, check=True)
# params are optional.
However, subprocess.run is blocking, i.e., the script will not exit unless you close your launched application.
You can in that case use the subprocess.Popen class. This invokes the process and allows you to communicate with it asynchronously. However, if your objective is only to launch an app and shut down your script, then just call it as you made a call to run. The links I have provided has some examples. there are platform level considerations to make in the case of the parent-child process relationships, e.g. keep child running if the parent dies, kill the child with the parent, keep both of them running independently and allow them to die separately. probably this answer and this answer would provide you with some hints.
However, if you just want to launch an application and nothing else, just use the system shell, no?

Related

Python3 - Issues with "subprocess.call()" function

my software uses the subprocess.call([sys.executable, SCRIPT_NAME] instruction in order to open others kind of scripts specified by the user using a GUI (Tkinter). I have two issue with this instruction:
the "command line" scripts start and close themeselves quicly and it means that the user can't interact with them. it's a weird behaviour because in all of them there is an input instruction, so they should wait an input by the user before to close themeselves. how can I solve this issue?
the "GUI" scripts instead, start without any kind of issue, but their "life", let me say, put in stuck the main script (it uses Tkinter). in this case I can interact with the second script but not with the main one. how can I call my other scripts with the subprocess.call() function whithout put in stuck the main one? from my point of view this issue happens because the second script is a part of the same process of the main one and in this case Tkinter has to wait. if we open the others scripts using different processes for all of them the main script would be free to live its life independently of the others. but how can I do it?

How to make a python script launched from subprocess.Popen stay open if an error occurs and closes when it returns normally?

Currently, I'm running this on Windows:
args = ['start', windowname, 'python', '-i', myscript]
subprocess.Popen(args, shell=True)
As you can see, I launch a subprocess running myscript in python's interactive mode. In my case, this means that once the script exits, regardless if it errors out or successfully completes, the window/shell stays open. However, I'd like it so that when myscript errors out, the window will stay open, and when myscript runs successfully, the window will close.
The reason I'm doing this is because I want to see the errors and the output leading up to the errors -- I'd prefer to not use some form of logging because it's easier for me to visually see the windows and outputs.
I don't think I can check the returncode because the process I'm interacting with is start/cmd, rather than python. Please correct me if I'm wrong!
Thanks!
I think the easiest way would be to wrap the whole thing in a small batch script that checks for python's return code (presumably set by you by calling sys.exit() with an appropriate return code).
This stackoverflow question covers how to get the return code (apparently it's in %errorlevel%), and you can keep the cmd window open by executing pause in a batch script.

Python: Redirect output to several consoles?

I have a main program, in which a user can call a sub-process (to download files) several times. Each time, I call aria2c using subprocess, and it will print the progress to stdin. Of course, it is desirable that the user can see the progress of each download seperately.
So the question is how can I redirect the output of each process to a seperate console window?
I'm a bit confused. Using subprocess.Popen(...) should spawn a new command prompt automatically for each call. What is aria2c? Is it a program you had written in python as well? Is it a 3rd party exe that writes to the command prompt window?
I can help you to redirect all the sub-processes output to the main command prompt, so it can be displayed inline.
Also, maybe you can give a little more detail on what is going on first, so I can understand your trouble a bit better.

Close pdf-file or exe-application from Python

My application is opening a pdf-file with os.startfile on user's request (push button). Is there any way to close this pdf when user pushes the button another time? If this is not done, I get the error:
WindowsError: [Error 32] The process cannot access the file because it is being used by another process: 'default_report.pdf'
Edit: Within Python I get: QPainter::begin(): Returned false (WindowsError comes from executable). Can I catch this err somehow with try? At least to ask user to close the pdf manually...
Another related question. My application is compiled as an executable and is called from another, VB6, application (also on push button). Is there any way to detect that executable is already running (exe-file always has the same location) from Python and kill it in this case prior to starting it again? Problem is similar, I get the error if I run the executable second time because they start to conflict (they use common db). From VB6 it doesn't work somehow, I don't know details...
Edit: solved with psutil (see my comment to the answer by jheyse)
p.s. I use Python 3.2, PyQt 4 and cx_freeze for exe production if it matters.
1.I don't think it's directy possible because as the docs say "startfile() returns as soon as the associated application is launched. There is no option to wait for the application to close, and no way to retrieve the application’s exit status."
2.To kill a process by name from python you can use the psutil module. Something like this (the following code will kill windows calculator if it is open):
for p in psutil.process_iter():
if p.name == 'calc.exe':
p.kill()

Color a Button after subprocess has finished

I have a Tk python program that creates a list of python files in the current directory and generates a button for each of them. When you click a button the corresponding python program is launched via subprocess in a new gnome-terminal. I'd like to switch the button's color to red after the subprocess has finished executing on the new terminal. Unfortunately, the button is changing color almost immediately.
from Tkinter import *
import os, subprocess
root = Tk()
buttonsD = {}
def launch(ourfile):
p=subprocess.Popen(["gnome-terminal","-e","python " + ourfile], shell=False)
buttonsD[ourfile].configure(bg='red')
dirlist=os.listdir(os.getcwd())
for fname in dirlist:
if fname.endswith('py') and fname != 'gui2.py':
buttonsD[fname] = Button(root,text=fname,command=lambda i=fname: launch(i))
buttonsD[fname].pack(side=TOP,expand=YES,fill=BOTH)
root.mainloop()
Almost immediately means that I can wait while p.poll == None, and see that it takes a moment for gnome-terminal to be created. But as soon as the terminal is created the button goes red, even though a process is still running in the new terminal. I can't create a new gnome-terminal and then communicate the process I'd like to run either. It seems gnome-terminal just creates a new instance of bash and then returns done, so there's a pipe error if I try to communicate to its stdin.
I believe gnome terminal is doing a double fork, in order to detach itself from the process group of its parent -- so what's actually your subprocess terminates almost immediately, as you observe, and everything is happening in a further descendant that you have no direct access to.
Unfortunately I don't believe gnome terminal offers any way to disable this double fork behavior; so, to find out when the "further descendant" is finished, you'll have to identify that process and monitor it periodically. Interacting directly with it is also a pretty tall order -- no easier than interacting with any "random" process you're not related to:-(.
There are two questions here: what command line to use to launch a Python program in gnome-terminal, and how to use subprocess in a Tkinter app. I only know about the latter.
subprocess.Popen returns immediately, which is why the button is turning red immediately. I think you probably need to make a list of which programs are running. Then write a function poll_processes which calls poll() on each running process, and when the result is not None, removes it from the list and turns the button red.
Then all you have to do is arrange for Tkinter to periodically call that function, which you can do by calling frame.after(msec, poll_processes) to schedule the first call to poll_processes and then having poll_processes do the same thing to schedule the next call.

Categories

Resources