我在 Python 3 中使用 psutil 编写了一个程序来获取当前正在运行的进程的内存详细信息。问题是我获得的值与 Windows 任务管理器中的值不同。具体来说,如何在 Python 中获取进程的私有(private)工作集大小?
最佳答案
psutil 调用 GetProcessMemoryInfo ,这不会破坏私有(private)内存与共享内存之间的工作集。要获取此信息,您可以使用 Windows performance counter API .我在下面演示的另一种方法是直接计算共享页面的数量。 QueryWorkingSet返回一组 PSAPI_WORKING_SET_BLOCK 条目(工作集中每页一个),您可以为这些条目统计具有 Shared 字段集的条目。您将需要一个进程句柄,您可以通过调用 GetCurrentProcess 来获得它。或 OpenProcess .要从页面转换为字节,请通过调用 GetPerformanceInfo 获取系统页面大小。或 GetSystemInfo .
这种方法的缺点是您需要PROCESS_VM_READ 和PROCESS_QUERY_INFORMATION 访问进程。如果当前用户是提升权限的管理员,通常启用 SeDebugPrivilege 可以绕过访问检查,“ protected ”进程除外。
from ctypes import *
from ctypes.wintypes import *
from collections import namedtuple
__all__ = ['query_working_set', 'working_set_size']
kernel32 = WinDLL('kernel32', use_last_error=True)
psapi = WinDLL('psapi', use_last_error=True)
PROCESS_VM_READ = 0x0010
PROCESS_QUERY_INFORMATION = 0x0400
ERROR_ACCESS_DENIED = 0x0005
ERROR_BAD_LENGTH = 0x0018
ULONG_PTR = WPARAM
SIZE_T = c_size_t
class PSAPI_WORKING_SET_BLOCK(Union):
class _FLAGS(Structure):
_fields_ = (('Protection', ULONG_PTR, 5),
('ShareCount', ULONG_PTR, 3),
('Shared', ULONG_PTR, 1),
('Reserved', ULONG_PTR, 3),
('VirtualPage', ULONG_PTR, 20))
_anonymous_ = '_flags',
_fields_ = (('Flags', ULONG_PTR),
('_flags', _FLAGS))
class PSAPI_WORKING_SET_INFORMATION(Structure):
_fields_ = (('NumberOfEntries', ULONG_PTR),
('_WorkingSetInfo', PSAPI_WORKING_SET_BLOCK * 1))
@property
def WorkingSetInfo(self):
array_t = PSAPI_WORKING_SET_BLOCK * self.NumberOfEntries
offset = PSAPI_WORKING_SET_INFORMATION._WorkingSetInfo.offset
return array_t.from_buffer(self, offset)
PPSAPI_WORKING_SET_INFORMATION = POINTER(PSAPI_WORKING_SET_INFORMATION)
def errcheck_bool(result, func, args):
if not result:
raise WinError(get_last_error())
return args
psapi.QueryWorkingSet.errcheck = errcheck_bool
psapi.QueryWorkingSet.argtypes = (
HANDLE, # _In_ hProcess
PPSAPI_WORKING_SET_INFORMATION, # _Out_ pv
DWORD) # _In_ cb
kernel32.GetCurrentProcess.restype = HANDLE
kernel32.OpenProcess.errcheck = errcheck_bool
kernel32.OpenProcess.restype = HANDLE
kernel32.OpenProcess.argtypes = (
DWORD, # _In_ dwDesiredAccess
BOOL, # _In_ bInheritHandle
DWORD) # _In_ dwProcessId
def query_working_set(pid=None):
"""Return the PSAPI_WORKING_SET_BLOCK array for the target process."""
if pid is None:
hprocess = kernel32.GetCurrentProcess()
else:
access = PROCESS_VM_READ | PROCESS_QUERY_INFORMATION
hprocess = kernel32.OpenProcess(access, False, pid)
info = PSAPI_WORKING_SET_INFORMATION()
base_size = sizeof(info)
item_size = sizeof(PSAPI_WORKING_SET_BLOCK)
overshoot = 0
while True:
overshoot += 4096
n = info.NumberOfEntries + overshoot
resize(info, base_size + n * item_size)
try:
psapi.QueryWorkingSet(hprocess, byref(info), sizeof(info))
break
except OSError as e:
if e.winerror != ERROR_BAD_LENGTH:
raise
return info.WorkingSetInfo
class PERFORMANCE_INFORMATION(Structure):
_fields_ = (('cb', DWORD),
('CommitTotal', SIZE_T),
('CommitLimit', SIZE_T),
('CommitPeak', SIZE_T),
('PhysicalTotal', SIZE_T),
('PhysicalAvailable', SIZE_T),
('SystemCache', SIZE_T),
('KernelTotal', SIZE_T),
('KernelPaged', SIZE_T),
('KernelNonpaged', SIZE_T),
('PageSize', SIZE_T),
('HandleCount', DWORD),
('ProcessCount', DWORD),
('ThreadCount', DWORD))
def __init__(self, *args, **kwds):
super(PERFORMANCE_INFORMATION, self).__init__(*args, **kwds)
self.cb = sizeof(self)
PPERFORMANCE_INFORMATION = POINTER(PERFORMANCE_INFORMATION)
psapi.GetPerformanceInfo.errcheck = errcheck_bool
psapi.GetPerformanceInfo.argtypes = (
PPERFORMANCE_INFORMATION, # _Out_ pPerformanceInformation
DWORD) # _In_ cb
WorkingSetSize = namedtuple('WorkingSetSize', 'total shared private')
def working_set_size(pid=None):
"""Return the total, shared, and private working set sizes
for the target process.
"""
wset = query_working_set(pid)
pinfo = PERFORMANCE_INFORMATION()
psapi.GetPerformanceInfo(byref(pinfo), sizeof(pinfo))
pagesize = pinfo.PageSize
total = len(wset) * pagesize
shared = sum(b.Shared for b in wset) * pagesize
private = total - shared
return WorkingSetSize(total, shared, private)
if __name__ == '__main__':
import sys
pid = int(sys.argv[1]) if len(sys.argv) > 1 else None
try:
total, shared, private = working_set_size(pid)
except OSError as e:
if e.winerror == ERROR_ACCESS_DENIED:
sys.exit('Access Denied')
raise
width = len(str(total))
print('Working Set: %*d' % (width, total))
print(' Shared: %*d' % (width, shared))
print(' Private: %*d' % (width, private))
例如:
C:\>tasklist /fi "imagename eq explorer.exe"
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
explorer.exe 2688 Console 1 66,048 K
C:\>workingset.py 2688
Working Set: 67465216
Shared: 59142144
Private: 8323072
以下演示了即使作为管理员也被拒绝访问系统进程。通常启用 SeDebugPrivilege 可以解决这个问题(注意权限必须存在于进程 token 中才能启用它;您不能只向 token 添加权限)。显示如何在访问 token 中启用和禁用特权超出了这个答案的范围,但下面我证明它确实有效,至少对于不 protected 进程。
C:\>tasklist /fi "imagename eq winlogon.exe"
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
winlogon.exe 496 Console 1 8,528 K
C:\>workingset.py 496
Access Denied
C:\>python
>>> from workingset import *
>>> from privilege import enable_privilege
>>> enable_privilege('SeDebugPrivilege')
>>> working_set_size(496)
WorkingSetSize(total=8732672, shared=8716288, private=16384)
关于python - 在 Windows 中获取与任务管理器相同的进程详细信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33216150/
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
如何使用RSpec::Core::RakeTask初始化RSpecRake任务?require'rspec/core/rake_task'RSpec::Core::RakeTask.newdo|t|#whatdoIputinhere?endInitialize函数记录在http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method没有很好的记录;它只是说:-(RakeTask)initialize(*args,&task_block)AnewinstanceofRake
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat