Ограничить использование оперативной памяти скрипта Python в Windows - PullRequest
0 голосов
/ 01 марта 2019

Моя программа может внезапно выделить много оперативной памяти в зависимости от использования.Я хочу ограничить ОЗУ, которое оно может взять из системы.

Я видел здесь: Ограничить использование ОЗУ программой python

Но это работает только для Unix.Любое решение для Windows?

Ответы [ 2 ]

0 голосов
/ 16 мая 2019

У меня была примерно та же проблема, что и у OP, за исключением того, что я хотел ограничить объем используемой физической памяти, а не виртуальной.Ответ @ 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)
0 голосов
/ 02 марта 2019

A Объект задания поддерживает ограничение выделенной памяти процесса.В Python мы можем реализовать это через PyWin32 или ctypes.

Обратите внимание, что до Windows 8 процесс может быть только в одном задании.Несколько распространенных случаев, когда это вызывает озабоченность, включают средство запуска py.exe (ассоциация по умолчанию для файлов .py), которое запускает python.exe в задании, и службу планировщика задач, которая запускает каждую задачу в задании.

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())
...