psutil.Process(pid).name 的替代方法
我测量了一下 psutil.Process(pid).name
这个功能的性能,发现它的速度比 psutil.Process(pid).exe
慢了十倍以上。因为后者需要不同的权限来访问路径,所以我不能仅仅从路径中提取文件名。我的问题是:有没有其他方法可以替代 psutil.Process(pid).name
,实现相同的功能?
2 个回答
3
从psutil 1.1.0版本开始,这个问题已经解决了,详情请查看https://code.google.com/p/psutil/issues/detail?id=426
6
你提到这是在Windows上使用的。我查看了一下psutil在Windows上的工作原理。看起来psutil.Process().name是通过Windows的工具帮助API来获取进程名称的。如果你查看psutil的Process代码并追踪.name,它会调用get_name()这个函数,具体在process_info.c文件里。这个函数会循环遍历你系统上的所有进程ID,直到找到你想要的那个。我觉得这可能是工具帮助API的一个限制。这也是为什么它比.exe慢,因为.exe使用的是不同的API路径,而你提到的那个路径需要额外的权限。
我想到的解决办法是使用ctypes和ctypes.windll直接调用Windows的ntapi。这样只需要PROCESS_QUERY_INFORMATION,这和PROCESS_ALL_ACCESS是不同的:
import ctypes
import os.path
# duplicate the UNICODE_STRING structure from the windows API
class UNICODE_STRING(ctypes.Structure):
_fields_ = [
('Length', ctypes.c_short),
('MaximumLength', ctypes.c_short),
('Buffer', ctypes.c_wchar_p)
]
# args
pid = 8000 # put your pid here
# define some constants; from windows API reference
MAX_TOTAL_PATH_CHARS = 32767
PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_IMAGE_FILE_NAME = 27
# open handles
ntdll = ctypes.windll.LoadLibrary('ntdll.dll')
process = ctypes.windll.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION,
False, pid)
# allocate memory
buflen = (((MAX_TOTAL_PATH_CHARS + 1) * ctypes.sizeof(ctypes.c_wchar)) +
ctypes.sizeof(UNICODE_STRING))
buffer = ctypes.c_char_p(' ' * buflen)
# query process image filename and parse for process "name"
ntdll.NtQueryInformationProcess(process, PROCESS_IMAGE_FILE_NAME, buffer,
buflen, None)
pustr = ctypes.cast(buffer, ctypes.POINTER(UNICODE_STRING))
print os.path.split(pustr.contents.Buffer)[-1]
# cleanup
ctypes.windll.kernel32.CloseHandle(process)
ctypes.windll.kernel32.FreeLibrary(ntdll._handle)