Автор оригинала: Mike Driscoll.
На днях я был поручено найти способ получить список всех беговых процессов на виртуальной машине Windows XP. Я также должен был включить информацию о том, сколько процессора и памяти используются каждый процесс. К счастью, это не должно быть удаленным скриптом, но тот, который мог бы работать на клиенте. После справедливого погубинка здесь и там я наконец нашел решение. В этой статье мы рассмотрим некоторые из отклонений, а также в результате возможного решения, которое происходит с трудовой платформой.
Один из первых скриптов, которые я нашел, был Это один назад с марта 2006 года:
# http://mail.python.org/pipermail/python-win32/2006-March/004340.html import win32com.client wmi=win32com.client.GetObject('winmgmts:') for p in wmi.InstancesOf('win32_process'): print p.Name, p.Properties_('ProcessId'), \ int(p.Properties_('UserModeTime').Value)+int(p.Properties_('KernelModeTime').Value) children=wmi.ExecQuery('Select * from win32_process where ParentProcessId=%s' %p.Properties_('ProcessId')) for child in children: print '\t',child.Name,child.Properties_('ProcessId'), \ int(child.Properties_('UserModeTime').Value)+int(child.Properties_('KernelModeTime').Value)
Этот скрипт требует от Pywin32 пакет работать. Однако, хотя это удобный маленький скрипт, он не показывает ничего, что я хочу, кроме процедуры. Я не забочусь о времени режима пользователя или ядра (I.e. Общее время процессора пользователем или ядром). Также я не очень люблю работать с черной магией ком, поэтому я закончил отказаться от этого из-за рук.
Далее был Активенский рецепт Отказ Это выглядело перспективным:
# http://code.activestate.com/recipes/303339-getting-process-information-on-windows/ import win32pdh, string, win32api def procids(): #each instance is a process, you can have multiple processes w/same name junk, instances = win32pdh.EnumObjectItems(None,None,'process', win32pdh.PERF_DETAIL_WIZARD) proc_ids=[] proc_dict={} for instance in instances: if instance in proc_dict: proc_dict[instance] = proc_dict[instance] + 1 else: proc_dict[instance]=0 for instance, max_instances in proc_dict.items(): for inum in xrange(max_instances+1): hq = win32pdh.OpenQuery() # initializes the query handle path = win32pdh.MakeCounterPath( (None,'process',instance, None, inum,'ID Process') ) counter_handle=win32pdh.AddCounter(hq, path) win32pdh.CollectQueryData(hq) #collects data for the counter type, val = win32pdh.GetFormattedCounterValue(counter_handle, win32pdh.PDH_FMT_LONG) proc_ids.append((instance,str(val))) win32pdh.CloseQuery(hq) proc_ids.sort() return proc_ids print procids()
Увы, хотя это также получило список процессов из моего окна Windows (наряду с PID), оно не дало мне никакой информации о процессоре и использовании памяти. Я думаю, что это может работать, если бы я использовал разные имена контра. Я предполагаю, что если вы хотите, вы можете понять, что информация с использованием MSDN. Я не хотел связываться с этим, поэтому я продолжал копать.
Этот рецепт привел меня к следующему на базе CTYPES:
# http://code.activestate.com/recipes/305279/ """ Enumerates active processes as seen under windows Task Manager on Win NT/2k/XP using PSAPI.dll (new api for processes) and using ctypes.Use it as you please. Based on information from http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q175030&ID=KB;EN-US;Q175030 By Eric Koome email ekoome@yahoo.com license GPL """ from ctypes import * #PSAPI.DLL psapi = windll.psapi #Kernel32.DLL kernel = windll.kernel32 def EnumProcesses(): arr = c_ulong * 256 lpidProcess= arr() cb = sizeof(lpidProcess) cbNeeded = c_ulong() hModule = c_ulong() count = c_ulong() modname = c_buffer(30) PROCESS_QUERY_INFORMATION = 0x0400 PROCESS_VM_READ = 0x0010 #Call Enumprocesses to get hold of process id's psapi.EnumProcesses(byref(lpidProcess), cb, byref(cbNeeded)) #Number of processes returned nReturned = cbNeeded.value/sizeof(c_ulong()) pidProcess = [i for i in lpidProcess][:nReturned] for pid in pidProcess: #Get handle to the process based on PID hProcess = kernel.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid) if hProcess: psapi.EnumProcessModules(hProcess, byref(hModule), sizeof(hModule), byref(count)) psapi.GetModuleBaseNameA(hProcess, hModule.value, modname, sizeof(modname)) print "".join([ i for i in modname if i != '\x00']) #-- Clean up for i in range(modname._length_): modname[i]='\x00' kernel.CloseHandle(hProcess) if __name__ == '__main__': EnumProcesses()
Это довольно умный, но я довольно плохой при разборе CTYPES. Это то, что я хочу учиться, но у меня был крайний срок, доггон! Кроме того, этот только показал список беговых процессов, но нет информации о них. К счастью, автор включал ссылку, но я решил продолжать смотреть.
Затем я нашел нить об использовании HIT Golden Handy WMI модуль Сделать такую вещь (ниже скопировано прямо из темы):
# http://mail.python.org/pipermail/python-win32/2003-December/001482.html >>> processes = WMI.InstancesOf('Win32_Process') >>> len(processes) 41 >>> [process.Properties_('Name').Value for process in processes] # get the process names [u'System Idle Process', u'System', u'SMSS.EXE', u'CSRSS.EXE', u'WINLOGON.EXE', u'SERVICES.EXE', u'LSASS.EXE', u'SVCHOST.EXE', u'SVCHOST.EXE', u'SVCHOST.EXE', u'SVCHOST.EXE', u'SPOOLSV.EXE', u'ati2evxx.exe', u'BAsfIpM.exe', u'defwatch.exe', u'inetinfo.exe', u'mdm.exe', u'rtvscan.exe', u'SCARDSVR.EXE', u'WLTRYSVC.EXE', u'BCMWLTRY.EXE', u'EXPLORER.EXE', u'Apoint.exe', u'carpserv.exe', u'atiptaxx.exe', u'quickset.exe', u'DSentry.exe', u'Directcd.exe', u'vptray.exe', u'ApntEx.exe', u'FaxCtrl.exe', u'digstream.exe', u'CTFMON.EXE', u'wuauclt.exe', u'IEXPLORE.EXE', u'Pythonwin.exe', u'MMC.EXE', u'OUTLOOK.EXE', u'LineMgr.exe', u'SAPISVR.EXE', u'WMIPRVSE.EXE'] Here is how to get a single process and get its PID. >>> p = WMI.ExecQuery('select * from Win32_Process where Name="Pythonwin.exe"') >>> [prop.Name for prop in p[0].Properties_] # let's look at all the process property names [u'Caption', u'CommandLine', u'CreationClassName', u'CreationDate', u'CSCreationClassName', u'CSName', u'Description', u'ExecutablePath', u'ExecutionState', u'Handle', u'HandleCount', u'InstallDate', u'KernelModeTime', u'MaximumWorkingSetSize', u'MinimumWorkingSetSize', u'Name', u'OSCreationClassName', u'OSName', u'OtherOperationCount', u'OtherTransferCount', u'PageFaults', u'PageFileUsage', u'ParentProcessId', u'PeakPageFileUsage', u'PeakVirtualSize', u'PeakWorkingSetSize', u'Priority', u'PrivatePageCount', u'ProcessId', u'QuotaNonPagedPoolUsage', u'QuotaPagedPoolUsage', u'QuotaPeakNonPagedPoolUsage', u'QuotaPeakPagedPoolUsage', u'ReadOperationCount', u'ReadTransferCount', u'SessionId', u'Status', u'TerminationDate', u'ThreadCount', u'UserModeTime', u'VirtualSize', u'WindowsVersion', u'WorkingSetSize', u'WriteOperationCount', u'WriteTransferCount'] >>> p[0].Properties_('ProcessId').Value # get our ProcessId 928
Это несколько прохладных вещей, и я использую золотые модули в некоторых из моих других кодов. Тем не менее, я все еще был неопределенным, что и какие счетчики использовать, чтобы добраться до моей информации. Я думал, что большая часть этого материала будет просто закодирована для меня или что-то в этом роде! Ну, оказалось, что там есть пакет, который имеет именно то, что мне нужно, и это работает на всех трех основных платформах! Удивительный!
Кроссплатформенный раствор!
Имя пакета есть Psutil И это было то, что я решил использовать. Вот что я оказался:
import os import psutil import time logPath = r'some\path\proclogs' if not os.path.exists(logPath): os.mkdir(logPath) separator = "-" * 80 format = "%7s %7s %12s %12s %30s, %s" format2 = "%7.4f %7.2f %12s %12s %30s, %s" while 1: procs = psutil.get_process_list() procs = sorted(procs, key=lambda proc: proc.name) logPath = r'some\path\proclogs\procLog%i.log' % int(time.time()) f = open(logPath, 'w') f.write(separator + "\n") f.write(time.ctime() + "\n") f.write(format % ("%CPU", "%MEM", "VMS", "RSS", "NAME", "PATH")) f.write("\n") for proc in procs: cpu_percent = proc.get_cpu_percent() mem_percent = proc.get_memory_percent() rss, vms = proc.get_memory_info() rss = str(rss) vms = str(vms) name = proc.name path = proc.path f.write(format2 % (cpu_percent, mem_percent, vms, rss, name, path)) f.write("\n\n") f.close() print "Finished log update!" time.sleep(300) print "writing new log data!"
Да, это бесконечная петля и да, это обычно очень плохое, что делать (кроме в программировании GUI). Однако для моей цели мне нужен способ проверить процессы пользователя каждые 5 минут или около того, чтобы увидеть, что вызывает, чтобы машина действовать так странно. Таким образом, скрипт должен работать навсегда и регистрировать результаты в уникальных именованных файлах. Это все этот сценарий, наряду с небольшим форматированием магии. Не стесняйтесь использовать его или нет, как вы видите подходящие.
Я надеюсь, что вы нашли эту коллекцию материала полезными. Надеюсь, это спасет вас всех копающих, я прошел!
ПРИМЕЧАНИЕ. В то время как этот последний скрипт, по-видимому, работает просто в Windows XP, в Windows 7 32 и 64-бит, вы получите «доступом отказано» Traceback, я подозреваю, что это вызвано повышенной безопасностью окна 7, но я постараюсь найти обходной путь.
Обновление (10/09/2010) – Люди Psutil не знают, почему это не работает, но один из их разработчиков подтвердил вопрос. Вы можете следовать на их Список групп Google Отказ