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

防止python睡眠模式(python上的Wakelock),python,python-3.x,linux,windows,sleep-mode,Python,Python 3.x,Linux,Windows,Sleep Mode,我如何在不使用其他操作系统(Ubuntu、Windows…)的情况下防止python上的睡眠模式,但在大多数情况下,我需要Linux解决方案 我正在制作一款能在大量时间内运行的应用程序。它使用了80%的CPU,所以用户只需启动这个应用程序,离开键盘。所以我想我需要像系统api或库这样的东西来锁定睡眠模式。我确信,它是存在的。例如,如果您在操作系统上打开任何视频播放器,您的(PC、笔记本电脑)将不会进入睡眠模式,在浏览器中也是如此 另外,在Android()或Windows中也有同样的情况,我遇到

我如何在不使用其他操作系统(Ubuntu、Windows…)的情况下防止python上的睡眠模式,但在大多数情况下,我需要Linux解决方案

我正在制作一款能在大量时间内运行的应用程序。它使用了80%的CPU,所以用户只需启动这个应用程序,离开键盘。所以我想我需要像系统api或库这样的东西来锁定睡眠模式。我确信,它是存在的。例如,如果您在操作系统上打开任何视频播放器,您的(PC、笔记本电脑)将不会进入睡眠模式,在浏览器中也是如此


另外,在Android()或Windows中也有同样的情况,我遇到过类似的情况,即一个进程花了足够长的时间自行执行,Windows将休眠。为了克服这个问题,我写了一个脚本

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

类窗口抑制器:
''在windows中防止操作系统睡眠/休眠;代码来源:
https://github.com/h3llrais3r/Deluge-PreventSuspendPlus/blob/master/preventsuspendplus/core.py
API文档:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa373208(v=vs.85).aspx''
ES_连续=0x8000000
ES_系统_必需=0x00000001
定义初始化(自):
通过
def抑制(自):
导入ctypes
打印(“防止Windows进入睡眠状态”)
ctypes.windell.kernel32.SetThreadExecutionState(
3.e|u连续|\
WindowsInhibitor.ES_系统(需要)
def解除抑制(自我):
导入ctypes
打印(“允许Windows进入睡眠状态”)
ctypes.windell.kernel32.SetThreadExecutionState(
(不连续)
要运行脚本,只需执行以下操作:

导入操作系统
osSleep=无
#在Windows中,防止操作系统在运行时休眠
如果os.name='nt':
osSleep=WindowsInhibitor()
osSleep.inhibit()
#做慢动作
如果是睡眠:
osSleep.unhibit()

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

我在这里发布了一个类似问题的解决方案:

因此,在逻辑上,请执行以下操作:

  • 通过subprocess.Popen(…)使用DBus命令清除休眠/挂起计数器
  • 使用psutil.cpu\u percent()查询cpu使用量 周期性地,或者在程序完成其工作后,将逻辑放入,以重新设置睡眠配置
  • 您可以在此处查看代码,了解有关如何修改代码的详细信息或提示:

    或者,您可以在运行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字节):

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

    要一次性运行上述所有设置(网络、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 &
    

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

    使用它非常简单。您可以使用
    standby\u lock
    或通过
    standbyllock
    作为上下文管理器选择decorator方法:

    ## 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
    特权,而且
    osx
    Darwin
    )尚未测试

    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'\003'
    
        _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
    

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

    import tkinter as tk
    import ctypes
    import sys
    
    def display_on():
        print("Always On")
        ctypes.windll.kernel32.SetThreadExecutionState(0x80000002)
    
    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()
    

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

    CLI 使用可选的
    -s
    标志也将保持屏幕打开

    Python API
    从wakepy导入集\u keepawake,取消设置\u keepawake
    设置唤醒(保持屏幕唤醒=错误)
    #做需要很长时间的事情
    unset_keepawake()
    
    这是什么类型的应用程序?是否使用
    tkinter
    ?您需要提供帮助您的人的详细信息。@mishsx不,它不使用tkinter,只是在终端上运行的简单应用程序。我不希望有跨平台的解决方案可用。您可能需要自己实现一个特定于平台的解决方案,该解决方案使用
    WakeLock
    SetThreadExecutionState
    或其他东西,具体取决于运行它的操作系统。我想您提到了
    windows
    。这就是为什么我的答案是专门为
    windows
    量身定做的。对于Linux,你可以参考-很棒的解决方案!你介意将其作为PyPI包发布吗?这非常好。您测试过linux/osx版本了吗?decorator和context manager方法中的一个警告是,如果您碰巧两次使用它,即使是在不同的进程中,第一次退出也会移除“锁”。谢谢您的建议!我的方法确实非常简单,考虑到多进程的情况,我没有想到这一点。我想我会按照@BenHagen的要求,考虑到多个应用程序,很快构建一个pypi包
    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'\003'
    
        _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
    
    import tkinter as tk
    import ctypes
    import sys
    
    def display_on():
        print("Always On")
        ctypes.windll.kernel32.SetThreadExecutionState(0x80000002)
    
    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()
    
    python -m wakepy [-s]