在 Windows 中限制 python 脚本 RAM 使用
Limit python script RAM usage in Windows
我的程序可以根据使用情况突然分配大量 RAM。
我想限制它可以从系统中获取的 RAM。
我看到这里:
但它只适用于 Unix。
Windows 的任何解决方案?
A Job object 支持限制进程的提交内存。在 Python 中,我们可以通过 PyWin32 或 ctypes 来实现。
注意在Windows8之前一个进程只能在一个Job中。几个常见的情况需要关注,包括 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())
我遇到了与 OP 大致相同的问题,除了我想限制使用的物理 RAM 量,而不是虚拟 RAM 量。 @eryksun 的回答和 limit_memory()
函数效果很好,但限制了可分配内存(虚拟内存)的总量。这是 his/her 代码的附加功能,它限制物理内存量("working set")。
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)
我的程序可以根据使用情况突然分配大量 RAM。 我想限制它可以从系统中获取的 RAM。
我看到这里:
但它只适用于 Unix。 Windows 的任何解决方案?
A Job object 支持限制进程的提交内存。在 Python 中,我们可以通过 PyWin32 或 ctypes 来实现。
注意在Windows8之前一个进程只能在一个Job中。几个常见的情况需要关注,包括 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())
我遇到了与 OP 大致相同的问题,除了我想限制使用的物理 RAM 量,而不是虚拟 RAM 量。 @eryksun 的回答和 limit_memory()
函数效果很好,但限制了可分配内存(虚拟内存)的总量。这是 his/her 代码的附加功能,它限制物理内存量("working set")。
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)