Python selenium CTRL+C closes chromedriver - python-2.7

How can I catch CTRL+C (a KeyboardInterrupt) without causing the chromedriver to close.
It closes the chromedriver when I run my script.py through cmd.
driver = webdriver.Chrome()
try:
while True:
#do stuff with chromedriver
except KeyboardInterrupt:
print "User pressed CTRL + C"
#do other stuff with chromedriver
It does catch the KeyboardInterrupt in my script, thus my script continues but the chromedriver also gets it and close itself.
EDIT 1:
The solution here doesn't work when you run the script through CMD or when you freeze the script with Pyinstaller and run it (IOError: [Errno 4] Interrupted function call)
EDIT 2:
I also tried by making the script ignore the Errno 4 (using try and except Exception) but still has the same result (chromedriver closes) so in short, this solution does not help at all.

Consider using the webdriver.Remote flavor. This option does not spawn a local version of the webdriver inside the interpreter, which should free you from the SIGINT hassle.
Initiate the webdriver in another shell - (chromedriver for Chrome, geckodriver for Firefox, etc.)
Take note of the listening port. I will use the defaults here: 9515 for chromedriver and 4444 for geckodriver.
In your python script:
Chrome:
driver=webdriver.Remote("http://127.0.0.1:9515",desired_capabilities=webdriver.DesiredCapabilities.CHROME)
Firerox:
driver=webdriver.Remote("http://127.0.0.1:4444",desired_capabilities=webdriver.DesiredCapabilities.FIREFOX)

I just tried #Krmit 's answer, with Selenium 4.8.2, python 3.11, and Geckodriver and it worked fine for what I wanted (to be able to cancel a sleep).
options=Options()
# options.profile = FirefoxProfile()
ps = signal.getsignal(signal.SIGINT)
signal.signal(signal.SIGINT, signal.SIG_IGN)
driver = webdriver.Firefox(service=FirefoxService(GeckoDriverManager().install()), options=options)
signal.signal(signal.SIGINT, ps)

You can also just disable SIGINT handling while starting the driver. Like so:
import signal
...
ps = signal.getsignal(signal.SIGINT) # backup signal handler
signal.signal(signal.SIGINT, signal.SIG_IGN) # ignore signal temporarily
... = webdriver.Chrome(...)
signal.signal(signal.SIGINT, ps) # restore original handler

Related

How to force quit my python-made exe

I've got a little python app that I used pyInstaller on to create an exe file:
import subprocess
try:
taskCommand = 'tasklist /FI "ImageName eq pc-client.exe"'
reply = subprocess.Popen(taskCommand, stdout = subprocess.PIPE).communicate()[0]
for line in reply.split("\n"):
if line.startswith("pc-client.exe"):
PID = line.split()[1]
print PID
except:
pass
try:
killCommand = ("TASKKILL /f /t /PID " + PID)
subprocess.Popen(killCommand, stdout = subprocess.PIPE).communicate()[0]
except:
pass
try:
print "Restarting Papercut Client..."
subprocess.Popen(r"\\server\path\to\file\filename.exe", stdout = subprocess.PIPE).communicate()[0]
except:
pass
sys.exit()
When the exe is run, it opens up in the windows command window, will run its code (it's non-interactive) and then I want the window to dissappear when its finished!
What should I put at the end of my python code to make the window close when completed. I've tried os.quit(), os._exit(), sys.quit() & sys.exit() but none of them actually close the window!
As I'm creating an exe from my code, should I use something else? I can't compile with the noconsole flag, as it needs it to actually run the commands...
Thanks.
You can block the windows command prompt from coming up at all by putting
console=False
in your spec file. For example:
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='YourApp',
console=False,
icon='IMGFolder\game_icon_cs6_icon.ico')
If you are running from the command line without a spec file, use the noconsole flag:
pyinstaller.py --noconsole yourscript.py
for more info on the PyInstaller options: https://pyinstaller.readthedocs.io/en/stable/usage.html#options
If you want the prompt to come up then close, sys.exit() works for me, but without seeing more code it will be hard to tell.
UPDATE
Since subprocesses are involved, keep in mind that the command prompt will remain open until all processes are resolved (parent and child).
It looks like you are killing the first task with its PID (I would print out the PID before you kill it to confirm you have the right one). Then you run the second task (the main file you want run?) but never kill it.
Are you trying to close the command prompt but keep the .exe running?
There is some good information about killing processes here:
How to kill a python child process created with subprocess.check_output() when the parent dies?

Restart Python script if finish or crash Windows

Now I have a infinite loop in my code for the script restart when finish. The problem is when script crash.
How I can restart script if crash?
infiniteloop.py
while True:
execfile("abc.py")
abc.py
print "1"
error
Do like this,
while True:
try:
execfile("abc.py")
except Exception as e:
print "Exception occured: ", e
There's probably not any way to have the script restart itself once it's crashed, but you could add some error handling like so:
while True:
try:
execfile("abc.py")
except:
pass
Alternatively, you could use shell scripting to run your wrapper repeatedly.

Killing a Windows 7 program using Python 2.7x

I currently have the below code:
processlist = []
for p in psutil.process_iter():
try:
process = psutil.Process(p.pid)
pname = process.name()
processlist.append(pname)
except:
pass
if "tor.exe" in processlist:
os.system("Taskkill /im tor.exe")
process = subprocess.Popen(r"C:\Program Files (x86)\Tor Browser\Browser\firefox.exe", stdout=subprocess.PIPE)
In essence,I want the Python code to kill the Tor Browser if it is open and to then reopen it. Nonetheless, when I run this code, the Tor browser displays a message stating that there is an error with the Browser and would the user like to close and restart the browser? I don't really want this to happen and so I'm just wondering if there is another way of closing the browser avoiding this confirmation prompt message?
Type taskkill /?
All you are doing is asking Tor (whatever that is) to close, ie send a WM_Close message. /f terminates an application.

Need to return a python-made webpage, without waiting for a subprocess to complete

OK so I am trying to run one python script (test1.py) and print something into a webpage at the end. I also want a subprocess (test2.py) to begin during this script. However, as it happens, test2.py is going to take longer to execute than test1. The problem that I am having is that test1.py is being held up until test2 completes. I have seen numerous people post similar questions but none of the solutions I've seen have fixed my issue.
Here's a heavily simplified version of my code that demonstrates the issue. I am running it on a local server, and displaying it in firefox.
test1.py:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import cgi
import cgitb; cgitb.enable()
import subprocess
form = cgi.FieldStorage()
print("Content-Type: text/html") # HTTP header to say HTML is following
print # blank line, end of headers
p = subprocess.Popen(['python','test2.py'])
print "script1 ended"
test2.py:
from time import sleep
print "script2 sleeping...."
sleep(60)
print "script2 ended"
Essentially I want to execute test1.py and have it say "script1 ended" in firefox, without having to wait 60 seconds for the subprocess to exit. I don't want anything from the test2 subprocess to show up.
EDIT: For anyone interested.. I solved the problem in windows by using os.startfile(), and as it turns out subprocess.Popen([...], stderr=subprocess.STDOUT, stdout=subprocess.PIPE) works in Linux. The scripts run in the background without delaying anything in the parent script when I do a wget on it.

How to set up autoreload with Flask+uWSGI?

I am looking for something like uWSGI + django autoreload mode for Flask.
I am running uwsgi version 1.9.5 and the option
uwsgi --py-autoreload 1
works great
If you're configuring uwsgi with command arguments, pass --py-autoreload=1:
uwsgi --py-autoreload=1
If you're using a .ini file to configure uwsgi and using uwsgi --ini, add the following to your .ini file:
py-autoreload = 1
For development environment you can try using
--python-autoreload uwsgi's parameter.
Looking at the source code it may work only in threaded mode (--enable-threads).
You could try using supervisord as a manager for your Uwsgi app. It also has a watch function that auto-reloads a process when a file or folder has been "touched"/modified.
You will find a nice tutorial here: Flask+NginX+Uwsgi+Supervisord
The auto-reloading functionality of development-mode Flask is actually provided by the underlying Werkzeug library. The relevant code is in werkzeug/serving.py -- it's worth taking a look at. But basically, the main application spawns the WSGI server as a subprocess that stats every active .py file once per second, looking for changes. If it sees any, the subprocess exits, and the parent process starts it back up again -- in effect reloading the chages.
There's no reason you couldn't implement a similar technique at the layer of uWSGI. If you don't want to use a stat loop, you can try using underlying OS file-watch commands. Apparently (according to Werkzeug's code), pyinotify is buggy, but perhaps Watchdog works? Try a few things out and see what happens.
Edit:
In response to the comment, I think this would be pretty easy to reimplement. Building on the example provided from your link, along with the code from werkzeug/serving.py:
""" NOTE: _iter_module_files() and check_for_modifications() are both
copied from Werkzeug code. Include appropriate attribution if
actually used in a project. """
import uwsgi
from uwsgidecorators import timer
import sys
import os
def _iter_module_files():
for module in sys.modules.values():
filename = getattr(module, '__file__', None)
if filename:
old = None
while not os.path.isfile(filename):
old = filename
filename = os.path.dirname(filename)
if filename == old:
break
else:
if filename[-4:] in ('.pyc', '.pyo'):
filename = filename[:-1]
yield filename
#timer(3)
def check_for_modifications():
# Function-static variable... you could make this global, or whatever
mtimes = check_for_modifications.mtimes
for filename in _iter_module_files():
try:
mtime = os.stat(filename).st_mtime
except OSError:
continue
old_time = mtimes.get(filename)
if old_time is None:
mtimes[filename] = mtime
continue
elif mtime > old_time:
uwsgi.reload()
return
check_for_modifications.mtimes = {} # init static
It's untested, but should work.
py-autoreload=1
in the .ini file does the job
import gevent.wsgi
import werkzeug.serving
#werkzeug.serving.run_with_reloader
def runServer():
gevent.wsgi.WSGIServer(('', 5000), app).serve_forever()
(You can use an arbitrary WSGI server)
I am afraid that Flask is really too bare bones to have an implementation like this bundled by default.
Dynamically reloading code in production is generally a bad thing, but if you are concerned about a dev environment, take a look at this bash shell script http://aplawrence.com/Unixart/watchdir.html
Just change the sleep interval to whatever suits your needs and substitute the echo command with whatever you use to reload uwsgi. I run uwsgi un master mode and just send a killall uwsgi command.