How to prevent a script being stopped by suspend? - python

I have a python alarm clock script, which needs to wake me up at some time.When I go to bed and leave it running, the laptop I use which has Linux Mint suspends itself after some time of inactivity.How can I prevent my script from being stopped and keep it running? My laptop is in my room and I need to close its lid because its light is annoying to sleep to.Here is my script.
import time
import sys
import webbrowser
alarm_HH = raw_input("Enter the hour you want to wake up at\n")
alarm_MM = raw_input("Enter the minute you want to wake up at\n")
print("You want to wake up at ", alarm_HH)
while True:
now = time.localtime()
if now.tm_hour == int(alarm_HH) and now.tm_min == int(alarm_MM):
webbrowser.open_new_tab("http://www.repeatmyvids.com/watch?v=SXLplRtMNfg&kmdom=youtube")
break
else:
timeout = 60 - now.tm_sec
if raw_input("Want me to stop?"):
break
[EDIT]
Ok so I figured it out.I installed python xlib module, which is a low level python library that you can install with sudo aptitude install python-xlib.I added a few lines of code that move the mouse pointer in order to prevent suspend, or sleep, so that my script can still work with lid closed and no input from anywhere.
d = display.Display()
s = d.screen()
root = s.root
root.warp_pointer(500,500)
d.sync()
I added a few of these, and the code now looks like this.
import time
import sys
import webbrowser
from Xlib import X, display
alarm_HH = input("Enter the hour you want to wake up at\n")
alarm_MM = input("Enter the minute you want to wake up at\n")
print("You want to wake up at ", alarm_HH)
while True:
now = time.localtime()
if now.tm_hour == int(alarm_HH) and now.tm_min == int(alarm_MM):
webbrowser.open_new_tab("http://www.repeatmyvids.com/watch?v=SXLplRtMNfg&kmdom=youtube")
break
else:
d = display.Display()
s = d.screen()
root = s.root
root.warp_pointer(500,500)
d.sync()
time.sleep( 5 )
root.warp_pointer(250,250)
d.sync()
time.sleep( 5 )
root.warp_pointer(100,100)
d.sync()
time.sleep( 5 )
root.warp_pointer(250,250)
d.sync()
Thanks to EngHamoud for giving me the idea to move the pointer in order to prevent suspend.

will if terminated because the script itself you could use the atexit
http://docs.python.org/2/library/atexit.html
if it's suspend because of the operating system "after period of time that the user haven't been active " i had faced that problem before then i've used the module xlib to control my mouse to move it randomly to it will be active
otherwise i think you gotta figure out the correct for your os configuration
hopefully i've answered what you've wondered about

Even in sleep mode S1 (your "suspend" I think), the CPU(s) stop executing instructions. So your program is no longer running -- hence cannot wake-up your computer...
You will certainly have to explore other ways of doing, such as configuring the real-time clock (which is still powered at sleep) to wake-up the computer. On embedded systems, you also have access to an hardware watchdog that could be (miss)used for that purpose. Don't know if this is available on PC.

The mouse trick appears to work in Windows too if you want to prevent suspension of your program after leaving it "idle" for a long time. It's doesn't appear to prevent the OS from sleeping though and pausing it that way :( Here's my asynchronous Windows solution using the mouse move concept:
Create one of these KeepActiveThread objects, and call start() / stop() as needed when you have a really long running processes.
import win32api # pywin32
import thread
import time
OSCILLATION_FREQ_SECS = 30
class KeepActiveThread() :
def __init__( self ) :
self.activeId_ = None
self.resurrectId_ = None
def start( self ) :
if self.activeId_ is None :
if self.resurrectId_ is None :
self.resurrectId_ = thread.start_new_thread(
self.__oscillateMouseCursor, () )
self.activeId_ = self.resurrectId_
def stop( self ) :
self.activeId_ = None
def __oscillateMouseCursor( self ) :
move = 1
while self.activeId_ :
move *= -1
try:
(x, y) = win32api.GetCursorPos()
win32api.SetCursorPos( (x+move, y) )
except: pass
time.sleep( OSCILLATION_FREQ_SECS )
self.resurrectId_ = None

I recomend using ctypes:
import ctypes
ES_CONTINUOUS = 0x80000000
ES_SYSTEM_REQUIRED = 0x00000001
ctypes.windll.kernel32.SetThreadExecutionState(
ES_CONTINUOUS | \
ES_SYSTEM_REQUIRED)

Related

Python SetThreadExecutionState: How do I prevent screen display from turning off?

I am on Windows. I want to run a Python Script that involves keyboard activity hence my PC mustn't lock screen or go to sleep. Instead of changing my PC Sleep Setting, I want to use Python code to keep my Screen Display On for the whole duration of my Python Script.
I modified the code here Prevent sleep mode python (Wakelock on python) but it doesn't work. My screen display still offs automatically. MY modified code as below:
class WindowsInhibitor:
'''Prevent OS sleep/hibernate in windows; code from:
https://github.com/h3llrais3r/Deluge-PreventSuspendPlus/blob/master/preventsuspendplus/core.py
API documentation:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa373208(v=vs.85).aspx'''
ES_CONTINUOUS = 0x80000000
ES_SYSTEM_REQUIRED = 0x00000001
ES_DISPLAY_REQUIRED= 0x00000002
def __init__(self):
pass
def inhibit(self):
import ctypes
print("Preventing Windows from going to sleep")
ctypes.windll.kernel32.SetThreadExecutionState(
WindowsInhibitor.ES_CONTINUOUS | \
WindowsInhibitor.ES_DISPLAY_REQUIRED)
def uninhibit(self):
import ctypes
print("Allowing Windows to go to sleep")
ctypes.windll.kernel32.SetThreadExecutionState(
WindowsInhibitor.ES_CONTINUOUS)
import os
osSleep = None
# in Windows, prevent the OS from sleeping while we run
if os.name == 'nt':
osSleep = WindowsInhibitor()
osSleep.inhibit()

APScheduler task not firing due to eventlet monkey_patch

I have some python code in which an APScheduler job is not firing. As context, I also have a handler that is looking a directory for file modifications in addition using eventlet/GreenPool to do multi-threading. Based on some troubleshooting, it seems like there's some sort of conflict between APScheduler and eventlet.
My output looks as follows:
2016-12-26 02:30:30 UTC (+0000): Finished Download Pass
2016-12-26 02:46:07 UTC (+0000): EXITING due to control-C or other exit signal
Jobstore default:
Time-Activated Download (trigger: interval[0:05:00], next run at: 2016-12-25 18:35:00 PST)
2016-12-26 02:46:07 UTC (+0000): 1
(18:35 PST = 02:35 UTC)...so it should have fired 11 minutes before I pressed control-C
from apscheduler import events ## pip install apscheduler
from apscheduler.schedulers.background import BackgroundScheduler
# Threading
from eventlet import patcher, GreenPool ## pip install eventlet
patcher.monkey_patch(all = True)
def setSchedule(scheduler, cfg, minutes = 60*2, hours = 0):
"""Set up the schedule of how frequently a download should be attempted.
scheduler object must already be declared.
will accept either minutes or hours for the period between downloads"""
if hours > 0:
minutes = 60*hours if minutes == 60 else 60*hours+minutes
handle = scheduler.add_job(processAllQueues,
trigger='interval',
kwargs={'cfg': cfg},
id='RQmain',
name='Time-Activated Download',
coalesce=True,
max_instances=1,
minutes=minutes,
start_date=dt.datetime.strptime('2016-10-10 00:15:00', '%Y-%m-%d %H:%M:%S') # computer's local time
)
return handle
def processAllQueues(cfg):
SQSpool = GreenPool(size=int(cfg.get('GLOBAL','Max_AWS_Connections')))
FHpool = GreenPool(size=int(cfg.get('GLOBAL','Max_Raw_File_Process')))
arSects = []
dGlobal = dict(cfg.items('GLOBAL'))
for sect in filter(lambda x: iz.notEqualz(x,'GLOBAL','RUNTIME'),cfg.sections()):
dSect = dict(cfg.items(sect)) # changes all key names to lowercase
n = dSect['sqs_queue_name']
nn = dSect['node_name']
fnbase = "{}_{}".format(nn,n)
dSect["no_ext_file_name"] = os.path.normpath(os.path.join(cfg.get('RUNTIME','Data_Directory'),fnbase))
arSects.append(mergeTwoDicts(dGlobal,dSect)) # section overrides global
arRes = []
for (que_data,spec_section) in SQSpool.imap(doQueueDownload,arSects):
if que_data: fileResult = FHpool.spawn(outputQueueToFiles,spec_section,que_data).wait()
else: fileResult = (False,spec_section['sqs_queue_name'])
arRes.append(fileResult)
SQSpool.waitall()
FHpool.waitall()
pr.ts_print("Finished Download Pass")
return None
def main():
cfgglob = readConfigs(cfgdir, datdir)
sched = BackgroundScheduler()
cron_job = setSchedule(sched, cfgglob, 5)
sched.start(paused=True)
try:
change_handle = win32file.FindFirstChangeNotification(cfgdir, 0, win32con.FILE_NOTIFY_CHANGE_FILE_NAME | win32con.FILE_NOTIFY_CHANGE_LAST_WRITE)
processAllQueues(cfgglob)
sched.resume() # turn the scheduler back on and monitor both wallclock and config directory.
cron_job.resume()
while 1:
SkipDownload = False
result = win32event.WaitForSingleObject(change_handle, 500)
if result == win32con.WAIT_OBJECT_0: # If the WaitForSO returned because of a notification rather than error/timing out
sched.pause() # make sure we don't run the job as a result of timestamp AND file modification
while 1:
try:
win32file.FindNextChangeNotification(change_handle) # rearm - done at start because of the loop structure here
cfgglob = None
cfgglob = readConfigs(cfgdir,datdir)
cron_job.modify(kwargs={'cfg': cfgglob}) # job_id="RQmain",
change_handle = win32file.FindFirstChangeNotification(cfgdir, 0, win32con.FILE_NOTIFY_CHANGE_FILE_NAME | win32con.FILE_NOTIFY_CHANGE_LAST_WRITE) # refresh handle
if not SkipDownload: processAllQueues(cfgglob)
sched.resume()
cron_job.resume()
break
except KeyboardInterrupt:
if VERBOSE | DEBUG: pr.ts_print("EXITING due to control-C or other exit signal")
finally:
sched.print_jobs()
pr.ts_print(sched.state)
sched.shutdown(wait=False)
If I comment out most of the processAllQueues function along with the eventlet includes at top, it fires appropriately. If I keep the
from eventlet import patcher, GreenPool ## pip install eventlet
patcher.monkey_patch(all = True)
but comment out processAllQueues up to the print line in the second-to-last line, it fails to fire the APScheduler, indicating that there's either a problem with importing patcher and GreenPool or with the monkey_patch statement. Commenting out the patcher.monkey_patch(all = True) makes it "work" again.
Does anyone know what an alternate monkey_patch statement would be that would work in my circumstances?
You have an explicit event loop watching for file changes. That blocks eventlet event loop from running. You have two options:
Wrap blocking calls (such as win32event.WaitForSingleObject()) in eventlet.tpool.execute()
Run eventlet.sleep() before/after blocking calls and make sure you don't block for too long.
eventlet.monkey_patch(thread=False) is shorter alternative to listing every other module as true. Generally you want thread=True when using locks or thread-local storage or threading API to spawn green threads. You may want thread=False if you genuinely use OS threads, like for funny GUI frameworks.
You shouldn't really consider Eventlet on Windows for running important projects. Performance is much inferior against POSIX. I didn't run tests on Windows since 0.17. It's rather for ease of development on popular desktop platform.

Raspberry Pi crash during python program (OR how is it possible to kill Linux???)

I build a keypad activated sensor with a Raspberry Pi and Python. Everything seems to go well but after a few minutes and several keypad entries, the Pi has a total crash and switches off immediately - no error messages pop up.
The script will continously wait for a keypad entry and if the code is correct, switch on a sensor, if it's not you have to try again. If the sensor is activated you have to put in the correct numbers to avoid an alarm being triggered after 30s)
Could anyone point me in the direction of what might be the problem? Here are the things I've tried so far without success
1) Exchange Pi to new Pi 2
2) Different OS, both NOOBS and Raspbian Wheezy
3) Different sensor (accelerometer vs IR sensor)
4) Disconnect monitor, keyboard and use SSH connection via Cygwin
5) Get log file until crash - log file was empty after reboot
python bad_script &> full_log.txt
6) Different log file command: causes instant crash and is also empty after reboot:
python script.py >> /logdir/script.py.log 2>&1
The question is: how am I able to crash Linux? If it's a memory problem, isn't there a prevention in linux to stop processed before they appear?
Here is the full script I am running:
import sys
from time import sleep
import threading
import signal
from matrix_keypad import RPi_GPIO1
import RPi.GPIO as GPIO
import smbus
import time
passcode = [1,2,3,4] # this is the correct code you have to enter
kp = RPi_GPIO1.keypad(columnCount = 3)
alarm_active = threading.Event() # shared variable used to control the sensor monitoring thread
alarm_active.clear() # Clear the alarm initially
monitor_thread = None # Global variable used to store the monitoring thread
#Set up all the pins correctio
GPIO.setmode(GPIO.BCM)
PINIR=7
GPIO.setup(7, GPIO.IN) # infrad-sensor
#Now activate the kaypad and listen for keypad inputs
def digit():
r = None
while r == None:
r = kp.getKey()
return r
def get_keycode():
# Function to loop around reading 4 keypresses in a row
# Compare against chosen code
# If match, switch the alarm state
entered = []
while len(entered) < 4:
key = digit()
sleep(0.5)
print key
entered.append( key )
if entered == passcode:
entered = []
print "Code correct"
switch_alarm_state()
else:
# Just clear the keypad buffer if the wrong code went in
# Could say "BAD CODE!" here, or even force immediate alarm perhaps
print "Wrong Code - Try again"
GPIO.output(27, True) # let red LED blink as indicator that code was wrong
time.sleep(1)
GPIO.output(27, False)
entered = []
def switch_alarm_state():
# Function to control the state of the alarm
# If the alarm should be on, run a thread monitoring the sensor
# If the alarm should be off, make sure the thread is stopped
global monitor_thread
if alarm_active.is_set():
# If the alarm is currently set, stop it
print "Alarm was abolished"
GPIO.output(17, False) #switch green LED off
alarm_active.clear() # Signals to the monitor thread that we wish to shut it down
monitor_thread.join() # Wait until the monitor thread has stopped
else:
# Alarm is not currently set, so start the sensor monitor thread going
print "Alarm was activated"
GPIO.output(17, True)
monitor_thread = threading.Thread( target=sensor_monitor )
alarm_active.set()
monitor_thread.start()
def sensor_monitor():
# Function to be run in a separate thread, monitoring the sensor
alarm_timer = None # Variable to hold a timer object that will fire the alarm
while alarm_active.is_set():
#print xrota
if GPIO.input(PINIR):
print "Alarm has been triggered"
if alarm_timer is None:
alarm_timer = threading.Timer( 30.0, fire_alarm )
alarm_timer.start()
sleep(0.5)
# The alarm must have been deactivated to get here
# Stop any outstanding alarms and shutdown
if alarm_timer is not None:
alarm_timer.cancel()
return
def fire_alarm():
# Here you implement the actions to be carried out by an alarm
print "Alarm is send to server"
msg = "Alarm"
publish.single("alarm/demo",msg, hostname="52.17.194.125")
def shutdown_handler( signum, frame ):
# Shut down the child thread nicely
alarm_active.clear()
monitor_thread.join()
if __name__ == '__main__': # This is the Python way to check you are being directly run, and not just imported by another script
signal.signal( signal.SIGINT, shutdown_handler ) # If you stop the script with ctrl+C, make sure it shuts down properly
signal.signal( signal.SIGTERM, shutdown_handler )
try:
while True:
get_keycode()
except KeyboardInterrupt:
GPIO.cleanup()
print "Quit program"

Listen onclick event in PyObjC

I try to display the current windows for each click on the system.
I do this code :
from AppKit import NSWorkspace
def getwindows():
activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
print activeAppName
return
def main():
getwindows()
main()
But only the current windows when i setup the script is displayed.
How can i bind this script in a loop with a click event ?
I already try to use Turtle but some errors appended.
Note that the activeApplication method of NSWorkSpace is deprecated. The following can be used to actively probe the running applications for their active status:
import AppKit
import time
rl = AppKit.NSRunLoop.currentRunLoop()
ws = AppKit.NSWorkspace.sharedWorkspace()
for i in xrange(10):
for app in ws.runningApplications():
if app.isActive():
print "active app:", app.localizedName()
date = AppKit.NSDate.date()
time.sleep(1)
rl.acceptInputForMode_beforeDate_( AppKit.NSDefaultRunLoopMode, date )
Active means it is the receiving keyboard input. Clicking on an application will cause it to become active. Note that the acceptInputForMode method must be called so that property changes are reflected in the current app. Run this program then click on various other applications -- you should see the active app change.
A kind of binding can be done through observers:
import AppKit
ws = AppKit.NSWorkspace.sharedWorkspace()
appL = ws.runningApplications()
class MyClass( AppKit.NSObject ):
def observeValueForKeyPath_ofObject_change_context_(self,
kpath, objid, change, context ):
print "path change", kpath, change['new'], appL[context].localizedName()
obj = MyClass.new()
for i in xrange(len(appL)):
appL[i].addObserver_forKeyPath_options_context_( obj,
"isActive", AppKit.NSKeyValueObservingOptionNew, i )
date = AppKit.NSDate.date().dateByAddingTimeInterval_( 10 )
rl = AppKit.NSRunLoop.currentRunLoop()
rl.acceptInputForMode_beforeDate_( AppKit.NSDefaultRunLoopMode, date )
for app in appL:
app.removeObserver_forKeyPath_( obj, "isActive" )
Run this program same as the last.
There are a few other properties of NSRunningApplication that you could probe/observe (such as hidden) but the list is quite short.

Checking for an open file with a timed refresh in Python

I'm wondering how I would go about having a function refresh itself every minute, and check if a certain file it open. I don't exactly know how to go about this, but heres an example of what I'm looking for:
def timedcheck():
if thisgame.exe is open:
print("The Program is Open!")
else:
print("The Program is closed!")
*waits 1 minute*
timedcheck()
I would also like the script to refresh the function "def timedcheck():" every minute, so it keeps checking if thisgame.exe is open.
I searched through the site already, all suggestions recommended using "import win32ui", which gives me an error when I do.
To repeat this check every minute:
def timedcheck():
while True:
if is_open("thisgame.exe"):
print("The Program is Open!")
else:
print("The Program is closed!")
sleep(60)
Since it's a .exe file, I assume that by "check if this file is open" you mean "check if thisgame.exe" is running. psutil should be helpful - I haven't tested the below code, so it may need some tweaking, but shows the general principle.
def is_open(proc_name):
import psutil
for process in psutil.process_iter():
if proc_name in process.name:
return True
return False
You can use sleep from the time module with an input of 60 for 1 minute delay between checks. You can open the file temporarily and close it if not needed. An IOError will occur if the file is already opened. Catch the error with an exception and the program will wait for another minute before trying again.
import time
def timedcheck():
try:
f = open('thisgame.exe')
f.close()
print("The Program is Closed!")
except IOError:
print("The Program is Already Open!")
time.sleep(60) #*program waits 1 minute*
timedcheck()
Here's a variation on #rkd91's answer:
import time
thisgame_isrunning = make_is_running("thisgame.exe")
def check():
if thisgame_isrunning():
print("The Program is Open!")
else:
print("The Program is closed!")
while True:
check() # ignore time it takes to run the check itself
time.sleep(60) # may wake up sooner/later than in a minute
where make_is_running():
import psutil # 3rd party module that needs to be installed
def make_is_running(program):
p = [None] # cache running process
def is_running():
if p[0] is None or not p[0].is_running():
# find program in the process list
p[0] = next((p for p in psutil.process_iter()
if p.name == program), None)
return p[0] is not None
return is_running
To install psutil on Windows for Python 2.7, you could run psutil-0.6.1.win32-py2.7.exe.

Categories