替代psutil.Process(pid).name

时间:2011-07-05 18:16:16

标签: python performance pywin32

我测量了psutil.Process(pid).name的性能,结果发现它比例psutil.Process(pid).exe慢了十倍多。因为这些函数中的最后一个需要在路径上具有不同的权限,所以我不能只从路径中提取文件名。我的问题是:psutil.Process(pid).name是否有其他方法可以做同样的事情?

2 个答案:

答案 0 :(得分:4)

你提到这是针对Windows的。我看了一下psutil对windows的作用。看起来像psutil.Process()。name正在使用windows工具帮助API。如果你看一下psutil的Process代码和trace .name,它会转到process_info.c中的get_name()。它循环遍历您系统上的所有pid,直到找到您正在寻找的那个。我认为这可能是toolhelp API的限制。但这就是为什么它比.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)

答案 1 :(得分:0)

自psutil 1.1.0起,此问题已修复,请参阅https://code.google.com/p/psutil/issues/detail?id=426