I am trying to write a downloader script (placed in unity luncher) using python that calls wget with all the right arguments. The script extracts url from clipboard and the file name from gtk primary clipboard, the one operated by text selection or copy and middle mouse click for paste. The code is rather simple.
import gtk
from os import system as sys
url = str(gtk.clipboard_get().wait_for_text())
name = str(gtk.clipboard_get(gtk.gdk.SELECTION_PRIMARY).wait_for_text())
if name.lower()=='none' :
sys("/usr/bin/canberra-gtk-play --id='dialog-warning'")
exit(1)
sys("/usr/bin/canberra-gtk-play --id='downloading'")
com='wget -c -t 0 "%s" -O "%s"' % (url,name)
sys("gnome-terminal -e '%s'" % com)
the script opens a terminal window and pints the wget output. The problem is that closing the gnome-terminal doesnt cause wget to exit, rather it runs in the background. Is it possible to stop this from happening
The problem is that, by design, wget ignores the SIGHUP which is sent when its parent process terminates.
One solution would be to use the python signal module to catch the SIGCHLD which should be sent to your script when you close the terminal window, and register a handler to explicitly send a SIGINT or SIGTERM to wget.
Related
I have a little program that uses TKinter to open a csv.
All works fine.
When the user chooses a file, I want the cursor and the active window to return to the Python shell.
I am using this:
os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')
When in IDLE, this works, when the program runs, but when I just double click the .py file and run it in the Python Shell, it says it can't find the path.
Anyone know the path I need?
Thanks,
Further research and this is my solution.
import win32gui as wg
from win32gui import GetWindowText, GetForegroundWindow
#This gets the details of the current window, the one running the program
aw = (GetForegroundWindow())
#Do some stuff..
#This tells the program to set the focus on the captured window
wg.SetForegroundWindow(aw)
I hope this helps anyone else looking for the same thing I was.
:-)
Try this, it refers to the running process via pid so it shouldn't matter exactly how you ran it:
import os
pid = os.getpid()
os.system("""/usr/bin/osascript -e 'tell application "System Events" to set frontmost of (first process whose unix id is %d) to true'""" % pid)
I want to just print some information and call an application e.g. notepad.
from subprocess import call
print("Opening Notepad++")
call([r"C:\Program Files (x86)\Notepad++\notepad++.exe"])
exit()
Problem now is that the terminal window doesn't automatically close. It stays open until I close the notepad window. How can I make the terminal window disappear automatically.
use Popen like so
import subprocess
subprocess.Popen(r'C:\Program Files (x86)\Notepad++\notepad++.exe', \
stdout=subprocess.PIPE, shell=False, creationflags = 0x08000000)
You need to call the notepad command with start COMMAND, like in Linux we use COMMAND & to fork the process into the background. in windows we use the start COMMAND
So you code refactored:
from subprocess import call
print("Opening Notepad++")
call([r"start C:\Program Files (x86)\Notepad++\notepad++.exe"])
exit()
Although note I don't have a windows machine to test on.
You could use pythonw.exe:
pythonw script.py
Or change its extension to pyw e.g. script.pyw and double click on it.
If you do that you should print "Opening Notepad++" to a popup window. See: Python Notification Popup that disappears
I have a python script which uses subprocess.check_call to launch Wine (Windows Emulator on Linux), then the wine launches Z:\\Program Files (x86)\\PeaZip\\peazip.exe.
Firstly, when I tested this python script in debugging mode python3 -u -m ipdb unpack_archive.py, and set breakpoint around wine launch and run statements step by step, the Wine runs peazip.exe successfully. That is, peazip successfully extract the PEA archive on Linux.
However, when I tested this python script not in debugging mode python3 unpack_archive.py, then I find peazip.exe doesn't extract PEA archive successfully. So I suspect there is a synchronization problem in wine or python subprocess.check_call().
Now my workaround is, inserting time.sleep(1.0) after launching wine :
elif 'PEA archive' in ftype:
if splitext(arcname)[1] != '.pea':
tmpfile = os.path.join(tmpdir, basename(arcname))+'.pea'
else:
tmpfile = os.path.join(tmpdir, basename(arcname))
shutil.copy(arcname, tmpfile)
subprocess.check_call(["wine", "/home/acteam/.wine/drive_c/Program Files (x86)/PeaZip/peazip.exe",
"-ext2here", to_wine_path(tmpfile)])
import time
time.sleep(1.0) # if we don't sleep, then peazip.exe won't extract file successfully
os.remove(tmpfile)
copy_without_symlink(tmpdir, outdir)
I checked the wine manual, it doesn't mention anything about synchronization. I also checked subprocess.check_call(). The document explicitly says the check_call() will wait for the command completed.
I don't want this workaround, because if the PEA archive file is very large, then the timeout value for sleep() must be larger, and we can't predict the sufficient timeout value before running it.
I referred to #jasonharper's suggestion. Use subprocess.check_output() instead of check_call()
elif 'PEA archive' in ftype:
if splitext(arcname)[1] != '.pea':
tmpfile = os.path.join(tmpdir, basename(arcname))+'.pea'
else:
tmpfile = os.path.join(tmpdir, basename(arcname))
shutil.copy(arcname, tmpfile)
subprocess.check_output(["wine", "/home/acteam/.wine/drive_c/Program Files (x86)/PeaZip/peazip.exe",
"-ext2here", to_wine_path(tmpfile)])
os.remove(tmpfile)
copy_without_symlink(splitext(tmpfile)[0], outdir)
I tested it with python3 unpack_archive.py Kevin.pea, which is a 2.0GB PEA archive. The extraction process costs 4 minutes 16 seconds. Three subfiles are unpacked successfully.
My understanding is that the wine executable is not the actual emulator - it just launches a background process called wineserver if it's not already running, tells it to run the Windows program, and then immediately exits itself - quite possibly before the Windows program has even started running.
One of the answers to this question suggests that piping the output of wine to another program will delay things until the Windows program actually exits. In Python terms, this would be equivalent to using check_output() instead of check_call(), although I haven't tried this myself.
Consider using advisory locking to block until the process has exited:
lockfile=open(tmpfile, 'a')
subprocess.check_call([
"wine", "/home/acteam/.wine/drive_c/Program Files (x86)/PeaZip/peazip.exe",
"-ext2here", to_wine_path(tmpfile)],
preexec_fn=lambda: fcntl.flock(lockfile, fcntl.LOCK_EX),
close_fds=False)
fcntl.flock(lockfile, fcntl.LOCK_EX)
Here, our preexec_fn (run after we've fork()ed off the subprocess but before wine has been started) grabs a lock, and after check_call() has returned, we then try to grab that lock ourselves -- which will block if it's not yet released.
(Note that you'll need to be sure that wine doesn't close that file descriptor itself prior to program exit; if it does, one way to avoid that is to create the lock on a descriptor passed as stdin, stdout or stderr).
I've got a long running python script that I want to be able to end from another python script. Ideally what I'm looking for is some way of setting a process ID to the first script and being able to see if it is running or not via that ID from the second. Additionally, I'd like to be able to terminate that long running process.
Any cool shortcuts exist to make this happen?
Also, I'm working in a Windows environment.
I just recently found an alternative answer here: Check to see if python script is running
You could get your own PID (Process Identifier) through
import os
os.getpid()
and to kill a process in Unix
import os, signal
os.kill(5383, signal.SIGKILL)
to kill in Windows use
import subprocess as s
def killProcess(pid):
s.Popen('taskkill /F /PID {0}'.format(pid), shell=True)
You can send the PID to the other programm or you could search in the process-list to find the name of the other script and kill it with the above script.
I hope that helps you.
You're looking for the subprocess module.
import subprocess as sp
extProc = sp.Popen(['python','myPyScript.py']) # runs myPyScript.py
status = sp.Popen.poll(extProc) # status should be 'None'
sp.Popen.terminate(extProc) # closes the process
status = sp.Popen.poll(extProc) # status should now be something other than 'None' ('1' in my testing)
subprocess.Popen starts the external python script, equivalent to typing 'python myPyScript.py' in a console or terminal.
The status from subprocess.Popen.poll(extProc) will be 'None' if the process is still running, and (for me) 1 if it has been closed from within this script. Not sure about what the status is if it has been closed another way.
This worked for me under windows 11 and PyQt5:
subprocess.Popen('python3 MySecondApp.py')
Popen.terminate(app)
where app is MyFirstApp.py (the caller script, running) and MySecondApp.py (the called script)
I have a python cgi/html that takes url and launches on epiphany-browser.
However, after the media/video is over, I need the browser to terminate.
On other posts, it seems there are ways to do this with vlc-media and other players. But I haven't found one with a browser.
Basic framework around the command looks like:
msg = form.getvalue("msg", "(no msg)")
.......
## in-progress of msg = "sudo -u vnc " + msg + " "
.......
from subprocess import *
print Popen(msg, shell=True, stdin=PIPE, stdout=PIPE).communicate()[0]
How do I implement such that the command (url) that gets executed shuts down after the streaming(youtube,cnn, etc) has been finished?
Thanks.
The simplest way to do this would be to use pkill. As you're looking to kill an instance of epiphany, a browser in the Unix family of operating systems, you'd use something like:
import os
os.system("pkill epiphany-browser")
If you executable is named something other than epiphany-browser change the second part of the pkill command to match.
Also bear in mind this will kill all processes with that name. To only kill the newest you can do something like:
import os
os.system("pkill -n epiphany-browser")
If you want to be really clever, you can try to graph the actual process number after you launch it:
import os
# launch stuff...
epiphanyPID=os.system("pgrep -n epiphany-browser")[2]
# do other stuff...
os.system("kill -9 " + epiphanyPID)
Also you should probably use the webbrowser object rather than opening with Popen. It lacks a close as far as I understand from the documentation, but for opening sessions it's the preferred solution. Epiphany is supported via the Galeon object:
20.1. webbrowser — Convenient Web-browser controller