【问题标题】:Limit python script RAM usage in Windows限制 Windows 中的 python 脚本 RAM 使用
【发布时间】:2019-07-23 18:01:09
【问题描述】:

我的程序可以根据使用情况突然分配大量 RAM。 我想限制它可以从系统中获取的 RAM。

我在这里看到: Limit RAM usage to python program

但它只适用于 Unix。 适用于 Windows 的任何解决方案?

【问题讨论】:

  • 试过将它与resource.RLIM_INFINITY结合起来吗? docs.python.org/3/library/resource.html#resource.RLIM_INFINITY
  • 与其限制您可以使用的内存量,我认为您最好以一种不那么消耗系统资源的更有效的方式执行您想要的操作。升级硬件是最糟糕的可扩展性。
  • @SharanArumugam 正如我所说,资源只是 unix 库
  • @Swift 对方程序我控制不了
  • @eryksun 怎么办?

标签: python windows resources ram ulimit


【解决方案1】:

我遇到了和 OP 差不多的问题,只是我想限制使用的物理 RAM 的数量,而不是虚拟的。 @eryksun 的回答和limit_memory() 函数效果很好,但限制了可分配内存(虚拟内存)的总量。这是他/她的代码的一个附加功能,它限制了物理内存(“工作集”)的数量。

def limit_working_set(memory_limit):
    if g_hjob is None:
        return
    info = win32job.QueryInformationJobObject(g_hjob, win32job.JobObjectBasicLimitInformation)
    info['MinimumWorkingSetSize'] = 50 * 4096  # default minimum value
    info['MaximumWorkingSetSize'] = memory_limit
    info['LimitFlags'] = (win32job.JOB_OBJECT_LIMIT_WORKINGSET)
    win32job.SetInformationJobObject(g_hjob, win32job.JobObjectBasicLimitInformation, info)

【讨论】:

    【解决方案2】:

    Job object 支持限制进程的已提交内存。在 Python 中,我们可以通过 PyWin32 或 ctypes 来实现。

    请注意,在 Windows 8 之前,一个进程只能在一个 Job 中。一些常见的情况包括 py.exe 启动器(.py 文件的默认关联),它在 Job 中运行 python.exe,以及 Task Scheduler 服务,它在 Job 中运行每个任务。

    PyWin32 示例

    import sys
    import warnings
    
    import winerror
    import win32api
    import win32job
    
    g_hjob = None
    
    def create_job(job_name='', breakaway='silent'):
        hjob = win32job.CreateJobObject(None, job_name)
        if breakaway:
            info = win32job.QueryInformationJobObject(hjob,
                        win32job.JobObjectExtendedLimitInformation)
            if breakaway == 'silent':
                info['BasicLimitInformation']['LimitFlags'] |= (
                    win32job.JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)
            else:
                info['BasicLimitInformation']['LimitFlags'] |= (
                    win32job.JOB_OBJECT_LIMIT_BREAKAWAY_OK)
            win32job.SetInformationJobObject(hjob,
                win32job.JobObjectExtendedLimitInformation, info)
        return hjob
    
    def assign_job(hjob):
        global g_hjob
        hprocess = win32api.GetCurrentProcess()
        try:
            win32job.AssignProcessToJobObject(hjob, hprocess)
            g_hjob = hjob
        except win32job.error as e:
            if (e.winerror != winerror.ERROR_ACCESS_DENIED or
                sys.getwindowsversion() >= (6, 2) or
                not win32job.IsProcessInJob(hprocess, None)):
                raise
            warnings.warn('The process is already in a job. Nested jobs are not '
                'supported prior to Windows 8.')
    
    def limit_memory(memory_limit):
        if g_hjob is None:
            return
        info = win32job.QueryInformationJobObject(g_hjob,
                    win32job.JobObjectExtendedLimitInformation)
        info['ProcessMemoryLimit'] = memory_limit
        info['BasicLimitInformation']['LimitFlags'] |= (
            win32job.JOB_OBJECT_LIMIT_PROCESS_MEMORY)
        win32job.SetInformationJobObject(g_hjob,
            win32job.JobObjectExtendedLimitInformation, info)
    
    def main():
        assign_job(create_job())
        memory_limit = 100 * 1024 * 1024 # 100 MiB
        limit_memory(memory_limit)
        try:
            bytearray(memory_limit)
        except MemoryError:
            print('Success: available memory is limited.')
        else:
            print('Failure: available memory is not limited.')
        return 0
    
    if __name__ == '__main__':
        sys.exit(main())
    

    【讨论】:

    • 感谢您的回答!但是,我仍然不明白如何使用此代码,例如,我有一个函数 run_pipeline(),我想为其设置 RAM 限制,我将 run_pipeline() 放在代码中的哪个位置?
    • @Lilianna,进程通过assign_job(create_job())分配给一个Job对象。然后limit_memory(memory_limit) 配置适用于作业中所有进程的内存限制。随后,调用您的run_pipeline 函数将受到内存限制。请注意,默认情况下,作业是在静默分离模式下创建的,因此只有当前进程会在作业中,即您不必担心子进程会受到此限制的影响。
    • 关于这个错误的任何想法:Assertion failed: error not defined [8] (C:\ci\zeromq_1599741307349\work\src\ip.cpp:481)我在上面运行代码时得到了这个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 2011-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多