Skip to content

Instantly share code, notes, and snippets.

@justengel
Last active August 18, 2020 17:39
Show Gist options
  • Save justengel/9d6d87761e004e274786471596c733e3 to your computer and use it in GitHub Desktop.
Save justengel/9d6d87761e004e274786471596c733e3 to your computer and use it in GitHub Desktop.
Keep windows 10 awake while this script is running.
"""Keep windows awake.
Build an executable with "pyinstaller ./keep_awake.py --noconsole --onefile"
Prevent OS sleep/hibernate in windows
* Derived from: https://stackoverflow.com/a/57647169/1965288
* 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
"""
import os
import ctypes
import atexit
import contextlib
__all__ = ['is_inhibited', 'inhibit', 'uninhibit', 'inhibitor']
ES_CONTINUOUS = 0x80000000
ES_SYSTEM_REQUIRED = 0x00000001
ES_DISPLAY_REQUIRED = 0x00000002
INHIBITED = False
def is_inhibited():
"""Return if inhibit was called and windows is not allowed to sleep."""
global INHIBITED
return INHIBITED
def inhibit():
"""Stop Windows from sleeping.
Returns:
success (bool): If True this is a windows machine and the computer should not sleep.
If False this is not a windows machine.
"""
global INHIBITED
if os.name != 'nt':
return False
print("Preventing Windows from going to sleep")
ctypes.windll.kernel32.SetThreadExecutionState(
ES_CONTINUOUS |
ES_SYSTEM_REQUIRED |
ES_DISPLAY_REQUIRED)
atexit.register(uninhibit)
INHIBITED = True
return INHIBITED
def uninhibit():
"""Allow Windows to sleep from inactivity again.
Returns:
success (bool): If True this is a windows machine and the computer should be allowed to sleep.
If False this is not a windows machine.
"""
global INHIBITED
if os.name != 'nt':
return False
print("Allowing Windows to go to sleep")
ctypes.windll.kernel32.SetThreadExecutionState(ES_CONTINUOUS)
try: atexit.unregister(uninhibit)
except (ValueError, TypeError, Exception): pass
INHIBITED = False
return True
@contextlib.contextmanager
def inhibitor():
"""Context manager to prevent windows from sleeping during this 'with' block."""
inhibit()
yield
uninhibit()
def keep_awake_widget():
"""Create a widget to keep windows awake or allow windows to sleep.
Returns:
container (QtWidgets.QWidget): Container widget.
status (QtWidgets.QLabel): Status widget.
btn (QtWidget.QPushButton): Button that allows windows to sleep or keeps windows awake.
toggle (callable/function): Function that allows windows to sleep or keeps windows awake (btn calls this).
"""
from qtpy import QtWidgets, QtCore
status = QtWidgets.QLabel()
btn = QtWidgets.QPushButton('')
btn.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
btn.setCheckable(True)
def toggle():
if is_inhibited():
uninhibit()
status.setText('Allowing Windows to go to sleep')
btn.setText('Keep Awake')
else:
inhibit()
status.setText('Preventing Windows from going to sleep')
btn.setText('Allow Sleep')
btn.toggled.connect(toggle)
btn.click()
container = QtWidgets.QWidget()
container.setLayout(QtWidgets.QVBoxLayout())
container.layout().addWidget(status, alignment=QtCore.Qt.AlignCenter)
container.layout().addWidget(btn, alignment=QtCore.Qt.AlignCenter)
return container, status, btn, toggle
if __name__ == '__main__':
try:
from qtpy import QtWidgets, QtCore
app = QtWidgets.QApplication([])
container, _, _, _ = keep_awake_widget()
window = QtWidgets.QMainWindow()
window.setWindowTitle('Keep Awake')
window.setCentralWidget(container)
window.show()
app.exec_()
# Uninhibit on close. Don't know if this is needed.
if is_inhibited():
uninhibit()
except (ImportError, Exception):
# QtPy and supporting Qt library (PySide2) is not installed. Run without a GUI.
with inhibitor():
input('Press Enter to allow windows to sleep from inactivity again. ')
# inhibit()
# input('Press Enter to allow windows to sleep from inactivity again. ')
# uninhibit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment