开发者

Alternative to psutil.Process(pid).name

I have measured the performance of psutil.Process(pid).name and it turns out that it is more than ten times slower than for example psutil.Process(pi开发者_StackOverflow中文版d).exe. Because the last one of these functions requires different privileges over the path, I cannot just just extract the filename from the path. My question is: Are there any alternatives to psutil.Process(pid).name, which does the same?


You mentioned this is for windows. I took a look at what psutil does for windows. It looks like psutil.Process().name is using the windows tool help API. If you look at psutil's Process code and trace .name, it goes to get_name() in process_info.c. It is looping through all the pids on your system until it finds the one you're looking for. I think this may be a limitation of the toolhelp API. But this is why it's slower than .exe, which uses a different API path, that (as you pointed out), requires additional privilege.

The solution I came up with is to use ctypes and ctypes.windll to call the windows ntapi directly. It only needs PROCESS_QUERY_INFORMATION, which is different than 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)


As of psutil 1.1.0 this problem has been fixed, see https://code.google.com/p/psutil/issues/detail?id=426

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜