防止睡眠模式python(python上的Wakelock)

2024-11-08 09:04:00
admin
原创
24
摘要:问题描述:如何在不使用不同操作系统(Ubuntu、Windows……)上的额外应用程序的情况下防止 Python 进入睡眠模式,但在大多数情况下我需要 Linux 解决方案我正在开发一款运行时间很长的应用。它占用了大约 80% 的 CPU,因此用户只需启动该应用,然后离开键盘即可。因此,我认为我需要一些类似系...

问题描述:

如何在不使用不同操作系统(Ubuntu、Windows……)上的额外应用程序的情况下防止 Python 进入睡眠模式,但在大多数情况下我需要 Linux 解决方案

我正在开发一款运行时间很长的应用。它占用了大约 80% 的 CPU,因此用户只需启动该应用,然后离开键盘即可。因此,我认为我需要一些类似系统 API 或库的东西来锁定睡眠模式。我确信它存在。例如,如果您在操作系统上打开任何视频播放器,您的(PC、笔记本电脑)将不会进入睡眠模式,浏览器中也是如此。

此外,Android( WakeLock)和Windows (SetThreadExecutionState)中也有同样的东西


解决方案 1:

在谷歌上搜索解决方案时,没有可用的软件包,所以我决定将其打包放到 PyPI:wakepy。我获得了跨平台支持的 PR,目前 wakepy 支持 Windows、Linux 和 macOS。

命令行界面

python -m wakepy [-p]

使用可选-p标志将使用演示模式,保持屏幕开启并解锁。

Python API

防止睡眠:

from wakepy import keep

with keep.running():
    # do stuff that takes long time

防止屏幕保护程序/屏幕锁定(和睡眠):

from wakepy import keep

with keep.presenting():
    # do stuff that takes long time

解决方案 2:

我遇到过类似的情况,一个进程执行时间太长,导致窗口休眠。为了解决这个问题,我写了一个脚本。

下面这段简单的代码可以防止这个问题。使用时,它会要求 Windows 在脚本运行时不要进入睡眠状态。(在某些情况下,例如电池电量耗尽时,Windows 会忽略您的请求。)

    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

        def __init__(self):
            pass

        def inhibit(self):
            import ctypes
            print("Preventing Windows from going to sleep")
            ctypes.windll.kernel32.SetThreadExecutionState(
                WindowsInhibitor.ES_CONTINUOUS | \n                WindowsInhibitor.ES_SYSTEM_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()

    # do slow stuff

    if osSleep:
        osSleep.uninhibit()

解决方案 3:

创建示例 TK 应用程序以保持 Windows 处于唤醒状态

import tkinter as tk
import ctypes
import sys

def display_on():
    global root
    print("Always On")
    ctypes.windll.kernel32.SetThreadExecutionState(0x80000002)
    root.iconify()

def display_reset():
    ctypes.windll.kernel32.SetThreadExecutionState(0x80000000)
    sys.exit(0)


root = tk.Tk()
root.geometry("200x60")
root.title("Display App")
frame = tk.Frame(root)
frame.pack()

button = tk.Button(frame,
                   text="Quit",
                   fg="red",
                   command=display_reset)
button.pack(side=tk.LEFT)
slogan = tk.Button(frame,
                   text="Always ON",
                   command=display_on)
slogan.pack(side=tk.LEFT)

root.mainloop()

解决方案 4:

我为它创建了一个名为stay-awake

PyPi:https://pypi.org/project/stay-awake/

Github:https ://github.com/singhsidhukuldeep/stay-awake

前往 https://pypi.org/project/stay-awake/
前往 https://pypi.org/project/stay-awake/
前往 https://pypi.org/project/stay-awake/
前往 https://pypi.org/project/stay-awake/
IT科技

Stay-Awake 是一个简单的平台独立 Python 包,可让您的系统保持唤醒状态而不影响工作流程!

  • 这会影响工作流程吗?

不,只有当您不进行任何鼠标移动时才会触发此操作!

  • 有 GUI 吗?

这旨在成为一个轻量级解决方案,所以到目前为止它只有一个 CLI!

  • 它是如何工作的?

如果在 60 秒内您没有移动鼠标,此脚本将自动随机移动鼠标约 1 到 4 个像素。不会有任何鼠标位移!如果您正在工作,这将完全不产生任何效果!

设置

安装包

pip3 install stay-awake

跑步

python3 -m stay-awake

您还可以指定自定义超时时间,例如:5 分钟(默认为 1 分钟)python3 -m stay-awake 5

在此处输入图片描述

解决方案 5:

根据我在互联网上找到的多种方法,我提出了以下模块。特别感谢@mishsx 提供的Windows解决方法。

使用它非常简单。您可以选择使用装饰器方法standby_lock或通过StandbyLock上下文管理器:

## decorator
@standby_lock
def foo(*args, **kwargs):
    # do something lazy here...
    pass

## context manager
with StandbyLock():
    # ...or do something lazy here instead
    pass

foo在执行期间,您的系统将保持唤醒状态。

注意:仍有一些注意事项,因为Linux可能需要sudo特权并且OS XDarwin)尚未测试。

from functools import wraps
import platform

class MetaStandbyLock(type):
    """
    """

    SYSTEM = platform.system()

    def __new__(cls, name: str, bases: tuple, attrs: dict) -> type:
        if not ('inhibit' in attrs and 'release' in attrs):
            raise TypeError("Missing implementations for classmethods 'inhibit(cls)' and 'release(cls)'.")
        else:
            if name == 'StandbyLock':
                cls._superclass = super().__new__(cls, name, bases, attrs)
                return cls._superclass
            if cls.SYSTEM.upper() in name.upper():
                if not hasattr(cls, '_superclass'):
                    raise ValueError("Class 'StandbyLock' must be implemented.")
                cls._superclass._subclass = super().__new__(cls, name, bases, attrs)
                return cls._superclass._subclass
            else:
                return super().__new__(cls, name, bases, attrs)

class StandbyLock(metaclass=MetaStandbyLock):
    """
    """

    _subclass = None

    @classmethod
    def inhibit(cls):
        if cls._subclass is None:
            raise OSError(f"There is no 'StandbyLock' implementation for OS '{platform.system()}'.")
        else:
            return cls._subclass.inhibit()

    @classmethod
    def release(cls):
        if cls._subclass is None:
            raise OSError(f"There is no 'StandbyLock' implementation for OS '{platform.system()}'.")
        else:
            return cls._subclass.release()

    def __enter__(self, *args, **kwargs):
        self.inhibit()
        return self

    def __exit__(self, *args, **kwargs):
        self.release()

class WindowsStandbyLock(StandbyLock):
    """
    """

    ES_CONTINUOUS      = 0x80000000
    ES_SYSTEM_REQUIRED = 0x00000001

    INHIBIT = ES_CONTINUOUS | ES_SYSTEM_REQUIRED
    RELEASE = ES_CONTINUOUS

    @classmethod
    def inhibit(cls):
        import ctypes
        ctypes.windll.kernel32.SetThreadExecutionState(cls.INHIBIT)

    @classmethod
    def release(cls):
        import ctypes
        ctypes.windll.kernel32.SetThreadExecutionState(cls.RELEASE)

class LinuxStandbyLock(metaclass=MetaStandbyLock):
    """
    """

    COMMAND = 'systemctl'
    ARGS = ['sleep.target', 'suspend.target', 'hibernate.target', 'hybrid-sleep.target']

    @classmethod
    def inhibit(cls):
        import subprocess
        subprocess.run([cls.COMMAND, 'mask', *cls.ARGS])

    @classmethod
    def release(cls):
        import subprocess
        subprocess.run([cls.COMMAND, 'unmask', *cls.ARGS])

class DarwinStandbyLock(metaclass=MetaStandbyLock):
    """
    """

    COMMAND = 'caffeinate'
    BREAK = b''

    _process = None

    @classmethod
    def inhibit(cls):
        from subprocess import Popen, PIPE
        cls._process = Popen([cls.COMMAND], stdin=PIPE, stdout=PIPE)

    @classmethod
    def release(cls):
        cls._process.stdin.write(cls.BREAK)
        cls._process.stdin.flush()
        cls._process.stdin.close()
        cls._process.wait()

def standby_lock(callback):
    """ standby_lock(callable) -> callable
        This decorator guarantees that the system will not enter standby mode while 'callable' is running.
    """
    @wraps(callback)
    def new_callback(*args, **kwargs):
        with StandbyLock():
            return callback(*args, **kwargs)
    return new_callback

解决方案 6:

Keep.Awake 中的逻辑将解决您在 ubuntu 或任何运行 Gnome(包括 Unity 的新旧版本)的 Linux 发行版上的问题,适用于 Wayland 和 X。它易于使用。

我在这里发布了类似问题的解决方案:https ://askubuntu.com/a/1231975/183131

因此从逻辑上来说,请执行以下操作:

  1. 通过 subprocess.Popen(...) 使用 DBus 命令清除睡眠/挂起计数器。

  2. 使用 psutil.cpu_percent() 定期查询 CPU 使用量,或者在程序完成其工作后放置逻辑以重新设置睡眠配置。

您可以在此处查看代码以获取有关如何修改代码的详细信息或提示: https: //launchpad.net/keep.awake

或者,您也可以在运行 CPU 密集型程序的 Linux 机器上运行 keepawake.py,它就会解决您的问题!它真的有效!

取自网页的示例用法:

要作为后台服务运行并将最低 CPU 负载设置为 13%:

nohup ./keepawake.py -c 13 -r > /dev/null 2>&1 &

作为后台服务运行,并在确定用户处于空闲状态之前将 15 分钟(900 秒)设置为用户活动空闲时间:

nohup ./keepawake.py -u 900 -r > /dev/null 2>&1 &

作为后台服务运行并将最小网络流量设置为 5KB(5120 字节):

nohup ./keepawake.py -s 5120 -r > /dev/null 2>&1 &

作为后台服务运行,并将计划设置为 1 小时后睡眠/挂起(仅当确定用户活动、CPU 和网络流量都处于空闲状态时才设置此值):

nohup ./keepawake.py -w 3600 -r > /dev/null 2>&1 &

要一次性运行上述所有设置(网络、CPU、用户空闲、睡眠计划),并将日志文件路径设置为“/home/$USER/sleep/log/Keep.Awake/”,并显示详细输出:

nohup ./keepawake.py -s 5120 -c 13 -u 900 -w 3600 -l /home/$USER/sleep/log/Keep.Awake/ -v Detail -r > /dev/null 2>&1 &

解决方案 7:

此代码用于每n分钟移动一次鼠标光标以保持系统保持唤醒。

首先安装pyautoguiPython。

运行以下代码:

import pyautogui
import time
import sys
from datetime import datetime
pyautogui.FAILSAFE = False
numMin = None
if ((len(sys.argv)<2) or sys.argv[1].isalpha() or int(sys.argv[1])<1):
    numMin = 2 # move cursor after numMin minutes
else:
    numMin = int(sys.argv[1])
while(True):
    x=0
    while(x<numMin):
        time.sleep(60)
        x+=1
    for i in range(0,50):
        pyautogui.moveTo(i*6+50,i*4)
    pyautogui.moveTo(1,1)
    for i in range(0,3):
        pyautogui.press("shift")
    print("Movement made at {}".format(datetime.now().time()))

解决方案 8:

您还可以使用 Caffeine+,这是一个小型托盘应用程序,可以让系统保持唤醒状态,而无需模拟键盘事件或完全干扰用户界面。https ://enemydevelopment.com/software/caffeine

解决方案 9:

在 Windows 上,不确定这是否会对任何人有所帮助,但上述方法对我不起作用。最终起作用的是运行第二个进程,该进程每 30 秒不断调用“shutdown /a”(中止关机)。Windows 说您大约有 1 分钟的时间来执行此操作,所以这就是 30 秒的原因。

完全愚蠢的解决方案,但无论如何,这是一个非常愚蠢的问题,没有操作系统提供的解决方案。

import subprocess
from time import sleep

def main():
    while(True):
        p = subprocess.Popen("shutdown /a", stdout=subprocess.PIPE, 
                             stderr=subprocess.PIPE)
        res = p.communicate()
        p.kill()
        sleep(30) # sleep 30 sec.

if __name__ == "__main__":
    main()

解决方案 10:

GUI 应用程序使窗口保持活动状态


Python3

安装库

pip install pywin32

将以下代码保存为alive.pyw文件

from ctypes import windll, wintypes, byref, c_uint, sizeof, Structure
import tkinter as tk
import ctypes
import sys
import threading
import time
import win32api
import win32con


stop_threads = True
SET_IDLE_TIME = 40 #in seconds

class LASTINPUTINFO(Structure):
    _fields_ = [
        ('cbSize', c_uint),
        ('dwTime', c_uint),
    ]

def get_idle_duration():
    lastInputInfo = LASTINPUTINFO()
    lastInputInfo.cbSize = sizeof(lastInputInfo)
    windll.user32.GetLastInputInfo(byref(lastInputInfo))
    millis = windll.kernel32.GetTickCount() - lastInputInfo.dwTime
    return millis / 1000.0


def press_key_2():
    global stop_threads
    while True:
        if not stop_threads:
            break
        idle_time = get_idle_duration() #seconds
        time.sleep(0.1)
        if idle_time < SET_IDLE_TIME:
            continue

        print("in ideal state pressing cltr")
        win32api.keybd_event(ord('x'), 0, win32con.KEYEVENTF_EXTENDEDKEY, 0)


#---------------- Monitor threads ------------------------------

t1 = threading.Thread(target=press_key_2, name='t1')
t1.daemon = True

#----------------- TK functions ----------------------

def display_on():
    global tk, t1, stop_threads
    stop_threads = True
    print("Always On")
    ctypes.windll.kernel32.SetThreadExecutionState(0x80000002)
    root.iconify()
    t1.start()
    # t2.start()

def display_reset():
    print("quit pressed")
    global stop_threads
    stop_threads = False
    ctypes.windll.kernel32.SetThreadExecutionState(0x80000000)
    sys.exit(0)



root = tk.Tk()
root.geometry("200x110")
root.title("Display App")
frame = tk.Frame(root)
frame.pack()

var = tk.StringVar()
label = tk.Label(frame, textvariable =  var)#, bd = 5, justify = tk.RIGHT, padx = 10, pady = 10)
var.set("")
button = tk.Button(frame,
                   text="Quit",
                   fg="red",
                   command=display_reset)

slogan = tk.Button(frame,
                   text="Always ON",
                   command=display_on)

label.pack(side=tk.BOTTOM,padx=0, pady=0)
slogan.pack(side=tk.LEFT,padx=15, pady=20)
button.pack(side=tk.LEFT,padx=15, pady=20)

root.mainloop()
ctypes.windll.kernel32.SetThreadExecutionState(0x80000000)

解决方案 11:

我编写了这段 Python 代码,它不仅可以让你的屏幕保持活动状态,还可以让你在不打扰你的情况下工作。基本上,你不必打开和关闭它。你可以让它保持运行并同时工作 -

这是 Python 代码 - https://github.com/sudhanshuism/keepPCAliveUserEnabled

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用