import psutil p = psutil.Process(pid=None)
pid=None
- идентификатор процесса.Класс Process()
модуля psutil
представляет процесс ОС с заданным идентификатором процесса. Если pid
опущен, то используется текущий pid
процесса (os.getpid()
). Если pid
не существует, то поднимается исключение psutil.NoSuchProcess
. В Linux pid
также может ссылаться на идентификатор потока (поле идентификатора, возвращаемое методом Process.threads()
).
При доступе к методам класса psutil.Process()
всегда нужно быть готовым перехватывать исключения psutil.NoSuchProcess
и psutil.AccessDenied
.
Чтобы однозначно идентифицировать процесс с течением времени можно использовать встроенную функцию hash()
(хэш определяется путем смешивания PID
процесса и времени создания). Таким образом, его также можно использовать с типом set
.
Примечание. Чтобы эффективно получать более одной информации о процессе одновременно, необходимо использовать диспетчер контекста
Process.oneshot()
или служебный методProcess.as_dict()
.
Обратите внимание, что этот класс связывается с процессом уникальным образом через его PID
. Это означает, что если процесс завершается, а ОС повторно использует свой PID
, то в конечном итоге можно взаимодействовать с другим процессом. Единственные исключения, для которых идентификация процесса предварительно проверяется (через PID
+ время создания), относятся к следующим методам: Process.nice()
, Process.ionice()
, Process.cpu_affinity()
, Process.rlimit()
, Process.children()
, Process.parent()
, Process.parents()
, Process.suspend()
, Process.resume()
, Process.send_signal()
, Process.terminate()
, Process.kill()
.
Чтобы предотвратить эту проблему для всех других методов, можно использовать метод Process.is_running()
перед запросом процесса или функцию psutil.process_iter()
, если процессы перебираются. Следует отметить, что если не иметь дело с очень "старыми" (неактивными) экземплярами процесса, то вряд ли это будет проблемой.
Process.oneshot()
:Менеджер контекста Process.oneshot()
значительно ускоряет одновременный поиск и извлечение различной информации об процессе. Различная внутренняя информация о процессе (например, Process.name()
, Process.ppid()
, Process.uids()
, Process.create_time()
, …) может быть получена с помощью одной процедуры чтения/извлечения, при этом возвращается только одно значение, а остальные отбрасываются.
При использовании этого контекстного менеджера внутренняя процедура чтения/извлечения информации выполняется один раз. В приведенном ниже примере, возвращается только интересующее значение, а остальная информация кэшируются. Последующие вызовы вернут кэшированное значение. Кэш очищается при выходе из блока диспетчера контекста. Совет состоит в том, чтобы использовать такое поведение всегда, когда нужно получить более одного значения о процессе.
>>> import psutil >>> p = psutil.Process() >>> with p.oneshot(): ... # выполним процедуру получения каких либо сведений. ... p.name() ... # Остальные данные будут извлекаться из кэша ... p.cpu_times() # возвращает кэшированное значение ... p.cpu_percent() # возвращает кэшированное значение ... p.create_time() # возвращает кэшированное значение ... p.ppid() # возвращает кэшированное значение ... p.status() # возвращает кэшированное значение
Process
.Process.pid
PID
процесса,Process.ppid()
родительский PID
процесса,Process.name()
имя процесса,Process.exe()
абсолютный путь процесса,Process.cmdline()
командная строка процесса,Process.environ()
переменные окружения процесса,Process.create_time()
время создания процесса,Process.as_dict()
извлекает информацию о нескольких процессах,Process.parent()
родительский процесс,Process.parents()
родители этого процесса,Process.status()
текущее состояние процесса,Process.cwd()
рабочий каталог процесса,Process.username()
имя пользователя, которому принадлежит процесс,Process.uids()
идентификатор пользователя этого процесса,Process.gids()
идентификатор группы этого процесса,Process.terminal()
терминал, связанный с этим процессом,Process.nice()
получает или устанавливает приоритет процесса,Process.ionice()
получает или устанавливает приоритет ввода-вывода процесса,Process.rlimit()
получает или устанавливает лимиты ресурсов процесса,Process.io_counters()
статистика ввода-вывода процесса,Process.num_ctx_switches()
количество переключений контекста,Process.num_fds()
количество открытых файловых дескрипторов,Process.num_handles()
количество используемых файловых дескрипторов,Process.num_threads()
количество используемых потоков,Process.threads()
потоки, открытые процессом,Process.cpu_times()
суммарное время обработки в секундах,Process.cpu_percent()
использование ЦП процессом в процентах,Process.cpu_affinity()
получает или устанавливает привязку процессора к процессу,Process.cpu_num()
на каком ЦП в данный момент работает этот процесс,Process.memory_info()
информацию о памяти, которую занимает/использует процесс,Process.memory_full_info()
предоставляет дополнительные показатели (USS
, PSS
и swap
),Process.memory_percent()
сравнивает память процесса с общей физической памятью,Process.memory_maps()
возвращает сопоставленные области памяти процесса,Process.children()
дочерние элементы этого процесса,Process.open_files()
файлы, открытые процессом,Process.connections()
соединения сокетов,Process.is_running()
проверяет, выполняется ли текущий процесс,Process.send_signal()
отправляет сигнал процессу,Process.suspend()
приостанавливает выполнение процесса,Process.resume()
возобновляет выполнения процесса,Process.terminate()
завершает процесс,Process.kill()
уничтожает текущий процесс,Process.pid
:Свойство Process.pid
возвращает собой PID
процесса. Это единственный (доступный только для чтения) атрибут класса.
Process.ppid()
:Метод Process.ppid()
возвращает родительский PID
процесса. В Windows возвращаемое значение кэшируется после первого вызова.
В POSIX не кэшируется, т.к. Process.ppid
может измениться, если процесс станет зомби.
Дополнительно смотрите методы
Process.parent()
иProcess.parents()
.
Process.name()
:Метод Process.name()
возвращает имя процесса. В Windows возвращаемое значение кэшируется после первого вызова.
В POSIX не кэшируется, т.к. имя процесса может измениться.
Process.exe()
:Метод Process.exe()
возвращает исполняемый процесс как абсолютный путь. В некоторых системах значение может быть пустой строкой. Возвращаемое значение кэшируется после первого вызова.
>>> import psutil >>> psutil.Process().exe() # '/usr/bin/python3.10'
Process.cmdline()
:Метод Process.cmdline()
возвращает командную строку, из которой был вызван этот процесс, представляет собой список строк. Возвращаемое значение не кэшируется, поскольку может измениться командная строка процесса.
>>> import psutil >>> psutil.Process().cmdline() # ['python', 'manage.py', 'runserver']
Process.environ()
:Метод Process.environ()
возвращает переменные окружения процесса в качестве словаря dict
.
Примечание. Возвращаемый словарь может не отражать изменения, внесенные после запуска процесса.
>>> import psutil >>> psutil.Process().environ() # { # 'LC_NUMERIC': 'it_IT.UTF-8', 'QT_QPA_PLATFORMTHEME': 'appmenu-qt5', # 'IM_CONFIG_PHASE': '1', 'XDG_GREETER_DATA_DIR': '/var/lib/lightdm-data/user', # 'GNOME_DESKTOP_SESSION_ID': 'this-is-deprecated', 'XDG_CURRENT_DESKTOP': 'Unity', # 'UPSTART_EVENTS': 'started starting', 'GNOME_KEYRING_PID': '', 'XDG_VTNR': '7', # 'QT_IM_MODULE': 'ibus', 'LOGNAME': 'user', 'USER': 'user', 'PATH': '/home/... # ... # }
Process.create_time()
:Метод Process.create_time()
возвращает время создания процесса в виде числа float
, выраженное в секундах с начала эпохи. Возвращаемое значение кэшируется после первого вызова.
>>> import psutil, datetime >>> p = psutil.Process() >>> p.create_time() # 1307289803.47 >>> t = datetime.datetime.fromtimestamp(p.create_time()) >>> t.strftime("%Y-%m-%d %H:%M:%S") # '2011-03-05 18:03:52'
Process.as_dict(attrs=None, ad_value=None)
:Метод Process.as_dict()
представляет собой служебный метод, извлекающий информацию о процессе в виде словаря.
Если атрибут attrs
указан, то это должен быть список строк, отражающих доступные имена атрибутов класса psutil.Process()
. Вот список возможных строковых значений: 'cmdline'
, 'connections'
, 'cpu_affinity'
, 'cpu_num'
, 'cpu_percent'
, 'cpu_times'
, 'create_time'
, 'cwd'
, 'environ'
, 'exe'
, 'gids'
, 'io_counters'
, 'ionice'
, 'memory_full_info'
, 'memory_info'
, 'memory_maps'
, 'memory_percent'
, 'name'
, 'nice'
, 'num_ctx_switches'
, 'num_fds'
, 'num_handles'
, 'num_threads'
, 'open_files'
, 'pid'
, 'ppid'
, 'status'
, 'terminal'
, 'threads'
, 'uids'
, 'username'
. Если аргумент attrs не передан, то предполагаются все общедоступные атрибуты только для чтения.
Аргумент ad_value
- это значение, которое присваивается ключу dict
в случае возникновения исключения psutil.AccessDenied
или psutil.ZombieProcess
при получении информации об этом конкретном процессе. Внутри Process.as_dict()
использует контекстный менеджер Process.oneshot()
.
>>> import psutil >>> p = psutil.Process() >>> p.as_dict(attrs=['pid', 'name', 'username']) # {'username': 'user', 'pid': 12366, 'name': 'python'} # список допустимых имен attrs >>> list(psutil.Process().as_dict().keys()) # ['status', 'cpu_num', 'num_ctx_switches', 'pid', 'memory_full_info', # 'connections', 'cmdline', 'create_time', 'ionice', 'num_fds', # 'memory_maps', 'cpu_percent', 'terminal', 'ppid', 'cwd', 'nice', # 'username', 'cpu_times', 'io_counters', 'memory_info', 'threads', # 'open_files', 'name', 'num_threads', 'exe', 'uids', 'gids', 'cpu_affinity', # 'memory_percent', 'environ']
Process.parent()
:Метод Process.parent()
возвращает родительский процесс как объект Process
, предварительно проверяя, был ли повторно использован PID
. Если родительский PID
не известен, то возвращает None
.
Дополнительно смотрите методы
Process.ppid()
иProcess.parents()
.
Process.parents()
:Метод Process.parents()
возвращает родителей этого процесса в виде списка экземпляров Process
. Если ни один из родителей не известен, то возвращает пустой список []
.
Дополнительно смотрите методы
Process.ppid()
иProcess.parent()
.
Process.status()
:Метод Process.status()
возвращает текущее состояние процесса в виде строки. Возвращаемая строка является одной из констант psutil.STATUS_*
Process.cwd()
:Метод Process.cwd()
возвращает текущий рабочий каталог процесса в качестве абсолютного пути.
Process.username()
:Метод Process.username()
возвращает имя пользователя, которому принадлежит процесс. В UNIX это рассчитывается с использованием реального идентификатора процесса.
Process.uids()
:Метод Process.uids()
возвращает реальный, эффективный и сохраненный идентификатор пользователя этого процесса в виде именованного кортежа.
Это то же самое, что и os.getresuid
, но может использоваться для любого PID
процесса.
Доступность: UNIX
Process.gids()
:Метод Process.gids()
возвращает реальный, эффективный и сохраненный идентификатор группы этого процесса в виде именованного кортежа.
Это то же самое, что и os.getresgid
, но может использоваться для любого PID
процесса.
Доступность: UNIX
Process.terminal()
:Метод Process.terminal()
возвращает терминал, связанный с этим процессом, если он есть, иначе None
.
Это похоже на команду tty
, но может использоваться для любого PID
процесса.
Доступность: UNIX
Process.nice(value=None)
:Метод Process.nice()
получает или устанавливает приоритет процесса. В UNIX это число, которое обычно находится в диапазоне от -20 до 20. Чем выше значение nice
, тем ниже приоритет процесса.
>>> import psutil >>> p = psutil.Process() # устанавливаем приоритет процесса >>> p.nice(10) # получаем приоритет процесса >>> p.nice() # 10
Эта функциональность также доступна как os.getpriority
и os.setpriority
.
В Windows это реализуется через API-интерфейсы Windows GetPriorityClass
и SetPriorityClass
, а значение является одной из констант psutil.*_PRIORITY_CLASS
, отражающих документацию MSDN.
Пример, который увеличивает приоритет процесса в Windows:
>>> p.nice(psutil.HIGH_PRIORITY_CLASS)
Process.ionice(ioclass=None, value=None)
:Метод Process.ionice()
получает или устанавливает приоритет ввода-вывода процесса. Если аргументы не указаны, то функция извлекает/получает приоритет, возвращая кортеж (ioclass, value)
в Linux и целое число ioclass
в Windows. Если предоставляется аргумент ioclass
, то функция пытается установить приоритет. В этом случае дополнительное значение value
можно указать только в Linux (чтобы еще больше повысить или понизить приоритет ввода-вывода).
Возможные значения ioclass
, зависящие от платформы.
ioprio_get
):IOPRIO_CLASS_RT
: (высокий) процесс каждый раз получает первый доступ к диску. Используйте его с осторожностью, так как это может привести к истощению всей системы. Можно указать дополнительный уровень приоритета, который варьируется от 0 (самый высокий) до 7 (самый низкий).IOPRIO_CLASS_BE
: (нормальный) значение по умолчанию для любого процесса, который не установил определенный приоритет ввода-вывода. Дополнительный уровень приоритета варьируется от 0 (самый высокий) до 7 (самый низкий).IOPRIO_CLASS_IDLE
: (низкий) получает время ввода-вывода, когда диск больше никому не нужен. Никакие дополнительные значения не принимаются.IOPRIO_CLASS_NONE
: возвращает, если ранее не был установлен приоритет.IOPRIO_HIGH
: наивысший приоритет.IOPRIO_NORMAL
: приоритет по умолчанию.IOPRIO_LOW
: низкий приоритет.IOPRIO_VERYLOW
: самый низкий приоритет.Пример того, как установить наивысший приоритет ввода-вывода в зависимости от платформы:
>>> import psutil >>> p = psutil.Process() >>> if psutil.LINUX: ... p.ionice(psutil.IOPRIO_CLASS_RT, value=7) ... else: ... p.ionice(psutil.IOPRIO_HIGH) # смотрим приоритет >>> p.ionice() pionice(ioclass=<IOPriority.IOPRIO_CLASS_RT: 1>, value=7)
Доступность: Linux, Windows Vista+
Process.rlimit(resource, limits=None)
:Метод Process.rlimit()
получает или устанавливает лимиты ресурсов процесса (см. man prlimit
).
Аргумент resource
является одной из констант psutil.RLIMIT_*
.
Аргумент limit
- это кортеж (soft, hard)
. Это то же самое, что и resource.getrlimit()
и resource.setrlimit()
, но может использоваться для любого PID
процесса, а не только для os.getpid()
. При получении, возвращаемое значение представляет собой кортеж (soft, hard)
. Каждое значение может быть либо целым, либо константой psutil.RLIMIT_*
.
Пример:
>>> import psutil >>> p = psutil.Process() # установим ограничение процессу, чтобы он мог # открыть открыть максимум 128 файловых дескрипторов >>> p.rlimit(psutil.RLIMIT_NOFILE, (128, 128)) # и мог создавать файлы размером не более 1024 байт >>> p.rlimit(psutil.RLIMIT_FSIZE, (1024, 1024)) # смотрим что получилось >>> p.rlimit(psutil.RLIMIT_FSIZE) # (1024, 1024)
Доступность: Linux, FreeBSD
Process.io_counters()
:Метод Process.io_counters()
возвращает статистику ввода-вывода процесса в виде именованного кортежа.
Для Linux можно обратиться к документации по файловой системе /proc
.
read_count
: количество совокупно выполненных операций чтения. Предполагается, что это подсчитывает количество системных вызовов, связанных с чтением, таких как read()
и pread()
в UNIX.write_count
: количество совокупно выполненных операций записи. Предполагается, что это подсчитывает количество системных вызовов, связанных с записью, таких как write()
и pwrite()
в UNIX.read_bytes
: количество кумулятивно прочитанных байтов. На BSD всегда -1.write_bytes
: количество кумулятивно записанных байт. На BSD всегда -1.Специфичные для Linux:
read_chars
(Linux): количество байтов, которые этот процесс совокупно передал системным вызовам read()
и pread()
. В отличие от read_bytes
, не имеет значения, происходил ли фактический ввод-вывод на физическом диске.write_chars
(Linux): количество байтов, которые этот процесс совокупно передал системным вызовам write()
и pwrite()
. В отличие от write_bytes
, не имеет значения, происходил ли фактический ввод-вывод на физический диск.Специфичные для Windows:
other_count
(Windows): количество выполненных операций ввода-вывода, отличных от операций чтения и записи.other_bytes
(Windows): количество байтов, передаваемых во время операций, отличных от операций чтения и записи.>>> import psutil >>> p = psutil.Process() >>> p.io_counters() # pio(read_count=454556, write_count=3456, read_bytes=110592, # write_bytes=0, read_chars=769931, write_chars=203)
Доступность: Linux, BSD, Windows, AIX
Process.num_ctx_switches()
:Метод Process.num_ctx_switches()
возвращает количество добровольных и непроизвольных переключений контекста, совокупно выполненных этим процессом.
Process.num_fds()
:Метод Process.num_fds()
возвращает количество файловых дескрипторов, открытых в данный момент этим процессом (не совокупно).
Доступность: UNIX
Process.num_handles()
:Метод Process.num_handles()
возвращает количество дескрипторов, используемых в данный момент этим процессом (не совокупно).
Доступность: Windows
Process.num_threads()
:Метод Process.num_threads()
возвращает количество потоков, используемых в данный момент этим процессом (не совокупно).
Process.threads()
:Метод Process.threads()
возвращает потоки, открытые процессом, в виде списка именованных кортежей. В OpenBSD этот метод требует привилегий root
.
id
: собственный идентификатор потока, назначенный ядром. Если pid
относится к текущему процессу, то он соответствует атрибуту native_id
класса threading.Thread
и может использоваться для ссылки на отдельные потоки Python, работающие в собственном приложении Python.user_time
: время, проведенное в пользовательском режиме.system_time
: время, проведенное в режиме ядра.Process.cpu_times()
:Метод Process.cpu_times()
возвращает именованный кортеж, представляющий суммарное время обработки в секундах (объяснение). Метод похож на os.times
, но может использоваться для любого PID
процесса.
user
: время, проведенное в пользовательском режиме.system
: время, проведенное в режиме ядра.children_user
: пользовательское время всех дочерних процессов (всегда 0 в Windows и macOS).children_system
: системное время всех дочерних процессов (всегда 0 в Windows и macOS).iowait
: (Linux) время, потраченное на ожидание завершения блокировки ввода-вывода. Это значение исключается из подсчета пользовательского и системного времени (т.к. ЦП не выполняет никакой работы).>>> import psutil >>> p = psutil.Process() >>> p.cpu_times() # pcputimes(user=0.03, system=0.67, children_user=0.0, # children_system=0.0, iowait=0.08) # совокупно, исключая детей и `iowait` >>> sum(p.cpu_times()[:2]) # 0.70
Process.cpu_percent(interval=None)
:Метод Process.cpu_percent()
возвращает число float
, представляющее использование ЦП процессом в процентах, которое также может быть равно 100,0 в случае, если процесс выполняет несколько потоков на разных ЦП.
Когда аргумент interval
> 0,0, то время обработки сравнивается с временем процессора системы, прошедшим до и после интервала (блокирующий вызов). Когда interval
равен 0,0 или None
, время обработки сравнивается с временем процессора системы, прошедшим с момента последнего вызова, и немедленно возвращается. Это означает, что при первом вызове он вернет бессмысленное значение 0.0, которое необходимо игнорировать. В этом случае для точности рекомендуется вызывать эту функцию второй раз с интервалом не менее 0,1 секунды между вызовами.
Пример:
>>> import psutil >>> p = psutil.Process() # блокирующий вызов >>> p.cpu_percent(interval=1) # 2.0 # неблокирующий вызов # (процент с момента последнего звонка) >>> p.cpu_percent(interval=None) # 2.9
Примечания:
- возвращаемое значение может быть > 100,0 в случае, если процесс выполняет несколько потоков на разных ядрах ЦП.
- возвращаемое значение явно не распределяется поровну между всеми доступными процессорами (в отличие от
psutil.cpu_percent()
). Это означает, что процесс цикла занятости, запущенный в системе с двумя логическими ЦП, будет сообщен как имеющий 100% загрузку ЦП вместо 50%. Это было сделано для того, чтобы соответствовать утилите UNIXtop
, а также чтобы было проще идентифицировать процессы, потребляющие ресурсы ЦП, независимо от количества ЦП. Следует отметить, чтоtaskmgr.exe
в Windows ведет себя не так (он сообщает об использовании 50%). Чтобы эмулировать поведениеtaskmgr.exe
, можно сделать:p.cpu_percent() / psutil.cpu_count()
.Предупреждение: при ПЕРВОМ ВЫЗОВЕ этого метода с
interval=0,0
илиinterval=None
, он вернет бессмысленное значение 0,0, которое необходимо игнорировать.
Process.cpu_affinity(cpus=None)
:Метод Process.cpu_affinity()
получает или устанавливает привязку процессора к текущему процессу. Привязка ЦП состоит в указании ОС запускать процесс только на ограниченном наборе ЦП (в Linux используется команда taskset
).
Если аргумент cpus
не передан, то метод возвращает текущую привязку ЦП в виде списка целых чисел. Если передан, то это должен быть список целых чисел, определяющих привязку для конкретных процессоров. Если передается пустой список, то предполагаются (и устанавливаются) все подходящие процессоры.
В некоторых системах, таких как Linux, это может означать все доступные логические ЦП, как в list(range(psutil.cpu_count()))
.
>>> import psutil >>> psutil.cpu_count() # 4 >>> p = psutil.Process() # получаем привязку >>> p.cpu_affinity() # [0, 1, 2, 3] # устанавливаем привязку # с этого момента процесс будет выполняться # только на процессорах #0 и #1 >>> p.cpu_affinity([0, 1]) >>> p.cpu_affinity() # [0, 1] # сбрасываем привязку ко всем # подходящим процессорам >>> p.cpu_affinity([])
Доступность: Linux, Windows, FreeBSD
Process.cpu_num()
:Метод Process.cpu_num()
возвращает, на каком ЦП в данный момент работает этот процесс (или какие ЦП использует). Возвращаемое число должно быть <= psutil.cpu_count()
. Во FreeBSD определенный процесс ядра может возвращать -1.
Метод можно использовать в сочетании с psutil.cpu_percent(percpu=True)
для наблюдения за рабочей нагрузкой системы, распределенной между несколькими процессорами.
Доступность: Linux, FreeBSD, SunOS
Смотрите пример "Пример вывода рабочей нагрузки, распределенной по разным ЦП".
Process.memory_info()
:Метод Process.memory_info()
возвращает именованный кортеж с полями (разными в зависимости от платформы), представляющей информацию о памяти, которую занимает/использует процесс. "Переносимые" (portable) поля, доступны на всех платформах (это rss
и vms
). Все числа выражены в байтах.
rss
: физическая память без подкачки, которую использовал процесс. В UNIX соответствует столбцу RES
утилиты top
. В Windows это псевдоним для поля wset
, и он соответствует столбцу Mem Usage
в taskmgr.exe
.vms
: общий объем виртуальной памяти, используемой процессом. В UNIX он соответствует столбцу VIRT
утилиты top
. В Windows это псевдоним для поля файла подкачки, и он соответствует столбцу VM Size
в taskmgr.exe
.shared
: (Linux) память, которая может быть потенциально разделена с другими процессами. Соответствует столбцу SHR
утилиты top
.text
(Linux, BSD): также известен как TRS
- объем памяти, выделенный для исполняемого кода. Соответствует столбцу CODE
утилиты top
.data
(Linux, BSD): также известен как DRS объем физической памяти, выделенный для кода, отличного от исполняемого. Соответствует столбцу DATA
утилиты top
.lib
(Linux): память, используемая разделяемыми библиотеками.dirty
(Linux): количество грязных страниц.pfaults
(macOS): количество ошибок страницы.pageins
(macOS): количество фактических страниц.Пример для Linux:
>>> import psutil >>> p = psutil.Process() >>> p.memory_info() # pmem(rss=15491072, vms=84025344, shared=5206016, # text=2555904, lib=0, data=9891840, dirty=0)
Process.memory_full_info()
:Метод Process.memory_full_info()
возвращает ту же информацию, что и Process.memory_info()
, плюс на некоторых платформах (Linux, macOS, Windows) также предоставляет дополнительные показатели (USS
, PSS
и swap
). Дополнительные метрики обеспечивают лучшее представление об "эффективном" потреблении памяти процессом (в случае USS
). Метод передает весь адрес процесса, таким образом, он обычно требует более высоких пользовательских привилегий, чем Process.memory_info()
, и работает значительно медленнее. На платформах, где дополнительные поля не реализованы, метод просто возвращает те же метрики, что и Process.memory_info()
.
Описание дополнительных метрик:
uss
(Linux, macOS, Windows): это память, которая уникальна для процесса и которая будет освобождена, если процесс будет завершен прямо сейчас.pss
(Linux): это объем памяти, совместно используемой с другими процессами, учитываемый таким образом, что объем делится поровну между процессами, которые его совместно используют. т.е. если процесс имеет 10 МБ для себя и 10 МБ для совместного использования с другим процессом, его PSS
будет 15 МБ.swap
(Linux): объем памяти, который был выгружен на диск.Обратите внимание, что
uss
, вероятно, является наиболее репрезентативной метрикой для определения того, сколько памяти фактически используется процессом. Он представляет собой объем памяти, который был бы освобожден, если бы процесс был завершен прямо сейчас.
Пример для Linux:
>>> import psutil >>> p = psutil.Process() >>> p.memory_full_info() # pfullmem(rss=10199040, vms=52133888, shared=3887104, # text=2867200, lib=0, data=5967872, dirty=0, # uss=6545408, pss=6872064, swap=0)
Смотрите пример "Подробное использование памяти всеми процессами".
Process.memory_percent(memtype="rss")
:Метод Process.memory_percent()
сравнивает память процесса с общей физической памятью системы и рассчитывает использование памяти процесса в процентах.
Аргумент memtype
- это строка, определяющая, с каким типом памяти процесса необходимо сравнить. Можно выбирать между именованными именами полей кортежа, возвращаемыми функциями Process.memory_info()
и Process.memory_full_info()
(по умолчанию 'rss'
).
Process.memory_maps(grouped=True)
:Метод Process.memory_maps()
возвращает сопоставленные области памяти процесса в виде списка именованных кортежей, поля которых являются разными в зависимости от платформы. Этот метод полезен для получения подробного представления об использовании памяти процесса (наиболее важным значением является private_*
память).
Если аргумент grouped
имеет значение True
, то сопоставленные области с одинаковым путем группируются вместе, а разные поля памяти суммируются. Если для параметра grouped
установлено значение False
, то каждый сопоставленный регион отображается как единый объект, а именованный кортеж также будет включать адресное пространство сопоставленного региона (addr
) и набор разрешений (perms
).
Смотрите пример "Пример вывода карты памяти процесса".
>>> import psutil >>> p = psutil.Process() >>> p.memory_maps() # [ # pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=32768, # size=2125824, pss=32768, shared_clean=0, # shared_dirty=0, private_clean=20480, private_dirty=12288, # referenced=32768, anonymous=12288, swap=0), # pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, # size=3842048, pss=3821568, shared_clean=0, # shared_dirty=0, private_clean=0, private_dirty=3821568, # referenced=3575808, anonymous=3821568, swap=0), # ...]
Доступность: Linux, Windows, FreeBSD, SunOS
Process.children(recursive=False)
:Метод Process.children()
возвращает дочерние элементы этого процесса в виде списка экземпляров Process
. Если аргумент recursive
равен True
, то возвращает всех родительских потомков. Пример псевдокода, предполагающий, что A == этот процесс:
A ─┐
│
├─ B (child) ─┐
│ └─ X (grandchild) ─┐
│ └─ Y (great grandchild)
├─ C (child)
└─ D (child)
>>> p.children() # B, C, D >>> p.children(recursive=True) # B, X, Y, C, D
Обратите внимание, что в приведенном выше примере, если процесс X исчезнет, то процесс Y также не будет возвращен, так как ссылка на процесс A будет потеряна.
Дополнительно смотрите "Пример уничтожение дерева процессов".
Process.open_files()
:Метод Process.open_files()
возвращает пути к обычным файлам, которые процесс открыл, в виде списка именованных кортежей, включая следующие поля:
path
: абсолютное имя файла;fd
: номер дескриптора файла, в Windows, всегда -1.Только для Linux:
position
(Linux): положение указателя в файле (смещение).mode
(Linux): строка, указывающая, как файл был открыт, аналогично аргументу mode
функции open()
. Нет разницы между файлами, открытыми в двоичном или текстовом режиме.flags
(Linux): флаги, которые были переданы базовой операции открытия файла os.open()
(например, os.O_RDONLY
, os.O_TRUNC
и т.д.).>>> import psutil >>> f = open('file.ext', 'w') >>> p = psutil.Process() >>> p.open_files() # [ # popenfile(path='/home/user/svn/psutil/file.ext', fd=3, # position=0, mode='w', flags=32769) # ]
Предупреждение для Windows: этот метод ненадежен из-за некоторых ограничений базового API Windows, может зависать при получении дескрипторов определенных файлов. Чтобы обойти такое поведение, модуль
psutil
порождает поток для определения имени дескриптора файла и убивает его, если он не отвечает через 100 мс. Это означает, что этот метод в Windows не гарантирует перечисление всех обычных файловых дескрипторов. Такое же ограничение имеют инструменты, такие какProcessHacker
.Предупреждение для BSD: этот метод может возвращать файлы с пустым путем из-за ошибки ядра, поэтому он ненадежен.
Process.connections(kind="inet")
:Метод Process.connections()
возвращает соединения сокетов, открытые процессом, в виде списка именованных кортежей. Чтобы получить общесистемные соединения, используйте psutil.net_connections()
.
Каждый именованный кортеж предоставляет 6 атрибутов:
fd
: дескриптор файла сокета. Если соединение относится к текущему процессу, это может быть передано socket.fromfd()
для получения пригодного для использования объекта сокета. В Windows и SunOS это значение всегда равно -1.family
: семейство адресов, либо AF_INET
, AF_INET6
, либо AF_UNIX
.type
: тип адреса: SOCK_STREAM
, SOCK_DGRAM
или SOCK_SEQPACKET
.laddr
: локальный адрес в виде (ip, port)
, именованный кортеж или путь path
в случае сокетов AF_UNIX. Для сокетов UNIX смотрите примечания ниже.raddr
: удаленный адрес в виде (ip, port)
, именованный кортеж или абсолютный путь path
в случае сокетов UNIX. Когда удаленная конечная точка не подключена, то возвращается пустой кортеж (AF_INET*)
или ''
(AF_UNIX). Для сокетов UNIX смотрите примечания ниже.status
: представляет состояние TCP-соединения. Возвращаемое значение является одной из констант psutil.CONN_*
(строка). Для сокетов UDP и UNIX это всегда будет psutil.CONN_NONE
.Аргумент kind
представляет собой строку, которая фильтрует соединения, соответствующие следующим критериям.
Аргумент kind | Соединения с использованием |
"inet" | IPv4 и IPv6 |
"inet4" | IPv4 |
"inet6" | IPv6 |
"tcp" | TCP |
"tcp4" | TCP поверх IPv4 |
"tcp6" | TCP поверх IPv6 |
"udp" | UDP |
"udp4" | UDP поверх IPv4 |
"udp6" | UDP поверх IPv6 |
"unix" | Сокет UNIX (как протоколы UDP, так и TCP) |
"all" | сумма всех возможных семейств и протоколов |
Пример:
>>> import psutil >>> p = psutil.Process(1694) >>> p.name() # 'firefox' >>> p.connections() # [ # pconn(fd=115, family=<AddressFamily.AF_INET: 2>, # type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), # raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'), # pconn(fd=117, family=<AddressFamily.AF_INET: 2>, # type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), # raddr=addr(ip='72.14.234.100', port=80), status='CLOSING'), # pconn(...) # ... # ]
Примечания:
- (Solaris) сокеты UNIX не поддерживаются.
- (Linux, FreeBSD) поле
raddr
для сокетов UNIX всегда имеет значение''
. Это ограничение ОС.- (в OpenBSD) поля
laddr
иraddr
для сокетов UNIX всегда имеют значение''
. Это ограничение ОС.- (AIX) всегда вызывается исключение
psutil.AccessDenied
, если только метод не запущен от имени пользователяroot
(lsof
делает то же самое).
Process.is_running()
:Метод Process.is_running()
проверяет, выполняется ли текущий процесс в текущем списке процессов. Метод надежен также в случае, если процесс упал, а его PID
повторно используется другим процессом.
Этот метод следует предпочесть выполнению функции psutil.pid_exists(p.pid)
.
Обратите внимание, что он также вернет True
, если процесс является зомби (p.status() == psutil.STATUS_ZOMBIE
).
Process.send_signal(signal)
:Метод Process.send_signal()
отправляет сигнал процессу (смотрите константы модуля signal
), упреждающе проверяя, был ли повторно использован PID
.
os.kill(pid, sig)
. SIGTERM
, CTRL_C_EVENT
и CTRL_BREAK_EVENT
, а SIGTERM
рассматривается как псевдоним для kill()
. Дополнительно смотрите "Пример уничтожение дерева процессов".
Process.suspend()
:Метод Process.suspend()
приостанавливает выполнение процесса с помощью сигнала SIGSTOP
, упреждающе проверяя, был ли повторно использован PID
.
os.kill(pid, signal.SIGSTOP)
. Process.resume()
:Метод Process.resume()
возобновляет выполнения процесса с сигналом SIGCONT
, упреждающе проверяющим, был ли повторно использован PID
.
os.kill(pid, signal.SIGCONT)
. Process.terminate()
:Метод Process.terminate()
завершает процесс сигналом SIGTERM
, предварительно проверив, был ли повторно использован PID
.
os.kill(pid, signal.SIGTERM)
][]. kill()
.Process.kill()
:Метод Process.kill()
уничтожает текущий процесс с помощью сигнала SIGKILL
, упреждающе проверяя, был ли повторно использован PID
.
os.kill(pid, signal.SIGKILL)
. TerminateProcess
.Process.wait(timeout=None)
:Метод Process.wait()
дожидается завершения PID
процесса. Возвращаемые значения различаются в UNIX и Windows.
В UNIX: если процесс завершился нормально, то возвращаемое значение представляет собой положительное целое число >= 0, указывающее код выхода. Если процесс был прерван по сигналу, то возвращает отрицательное значение сигнала, вызвавшего завершение (например, -SIGTERM
). Если PID
не является потомком os.getpid
(текущего процесса), то просто будет ждать, пока процесс не исчезнет, и вернет None
. Если PID
не существует, то немедленно возвращает None
.
В Windows: всегда возвращает код выхода, который является положительным целым числом, возвращаемым Windows API GetExitCodeProcess
.
Аргумент timeout
выражается в секундах. Если указан и процесс все еще жив, то вызывает исключение TimeoutExpired
. При timeout=0
можно использовать в неблокирующих приложениях: метод либо возвращает значение немедленно, либо поднимет значение TimeoutExpired
.
Возвращаемое значение кэшируется. Для ожидания нескольких процессов нужно использовать функцию psutil.wait_procs()
.
>>> import psutil >>> p = psutil.Process(9891) >>> p.terminate() >>> p.wait() # <Negsignal.SIGTERM: -15>
Дополнительно смотрите "Пример уничтожение дерева процессов".
import os import signal import psutil def kill_proc_tree(pid, sig=signal.SIGTERM, include_parent=True, timeout=None, on_terminate=None): """Уничтожает дерево процессов (включая внуков) сигналом 'sig' и возвращает кортеж `(gone, still_alive)`. Аргумент 'on_terminate', если указан, является функцией обратного вызова, которая вызывается, как только завершается дочерний процесс. """ assert pid != os.getpid(), "не может убить сама себя" parent = psutil.Process(pid) children = parent.children(recursive=True) if include_parent: children.append(parent) for p in children: try: p.send_signal(sig) except psutil.NoSuchProcess: pass gone, alive = psutil.wait_procs(children, timeout=timeout, callback=on_terminate) return (gone, alive)
import collections import os import sys import time import psutil from psutil._compat import get_terminal_size if not hasattr(psutil.Process, "cpu_num"): sys.exit("platform not supported") def clean_screen(): if psutil.POSIX: os.system('clear') else: os.system('cls') def main(): num_cpus = psutil.cpu_count() if num_cpus > 8: num_cpus = 8 # try to fit into screen cpus_hidden = True else: cpus_hidden = False while True: # вывод заголовка clean_screen() cpus_percent = psutil.cpu_percent(percpu=True) for i in range(num_cpus): print("CPU %-6i" % i, end="") if cpus_hidden: print(" (+ hidden)", end="") print() for _ in range(num_cpus): print("%-10s" % cpus_percent.pop(0), end="") print() # процессы procs = collections.defaultdict(list) for p in psutil.process_iter(['name', 'cpu_num']): procs[p.info['cpu_num']].append(p.info['name'][:5]) curr_line = 3 while True: for num in range(num_cpus): try: pname = procs[num].pop() except IndexError: pname = "" print("%-10s" % pname[:10], end="") print() curr_line += 1 if curr_line >= get_terminal_size()[1]: break time.sleep(1) if __name__ == '__main__': main()
Вывод сценария:
$ python3 test.py CPU 0 CPU 1 CPU 2 CPU 3 CPU 4 CPU 5 CPU 6 CPU 7 19.8 20.6 18.2 15.8 6.9 17.3 5.0 20.4 gvfsd pytho kwork chrom unity kwork kwork kwork chrom chrom indic ibus- whoop nfsd (sd-p gvfsd ibus- cat at-sp chrom Modem nfsd4 light upsta ibus- iprt- ibus- nacl_ cfg80 kwork nfsd bluet chrom irqba gpg-a chrom ext4- biose nfsd dio/n chrom acpid bamfd nvidi kwork scsi_ sshd rpc.m upsta rsysl dbus- nfsd biose scsi_ ext4- polki rtkit avahi upowe Netwo scsi_ biose UVM T irq/9 [...]
Пример представляет собой подробный вывод использования памяти всеми (поддерживаемыми запросом) процессами. Процессы сортируются по памяти USS
, т.е. наиболее репрезентативный показатель для определения объема памяти фактически используемой процессом.
Пример похож на утилиту командной строки smem
в Linux:
import sys import psutil if not (psutil.LINUX or psutil.MACOS or psutil.WINDOWS): sys.exit("платформа не поддерживается") def convert_bytes(n): symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') prefix = {} for i, s in enumerate(symbols): prefix[s] = 1 << (i + 1) * 10 for s in reversed(symbols): if n >= prefix[s]: value = float(n) / prefix[s] return '%.1f%s' % (value, s) return "%sB" % n def main(): ad_pids = [] procs = [] for p in psutil.process_iter(): with p.oneshot(): try: mem = p.memory_full_info() info = p.as_dict(["cmdline", "username"]) except psutil.AccessDenied: ad_pids.append(p.pid) except psutil.NoSuchProcess: pass else: p._uss = mem.uss p._rss = mem.rss if not p._uss: continue p._pss = getattr(mem, "pss", "") p._swap = getattr(mem, "swap", "") p._info = info procs.append(p) procs.sort(key=lambda p: p._uss) templ = "%-7s %-7s %7s %7s %7s %7s %7s" print(templ % ("PID", "User", "USS", "PSS", "Swap", "RSS", "Cmdline")) print("=" * 78) for p in procs[:86]: cmd = " ".join(p._info["cmdline"])[:50] if p._info["cmdline"] else "" line = templ % ( p.pid, p._info["username"][:7] if p._info["username"] else "", convert_bytes(p._uss), convert_bytes(p._pss) if p._pss != "" else "", convert_bytes(p._swap) if p._swap != "" else "", convert_bytes(p._rss), cmd, ) print(line) if ad_pids: print("warning: access denied for %s pids" % (len(ad_pids)), file=sys.stderr) if __name__ == '__main__': sys.exit(main())
Вывод сценария:
$ python3 test.py PID User Cmdline USS PSS Swap RSS ============================================================================== [...] 3986 user /usr/bin/python3 /usr/bin/indi 15.3M 16.6M 0B 25.6M 3906 user /usr/lib/ibus/ibus-ui-gtk3 17.6M 18.1M 0B 26.7M 3991 user python /usr/bin/hp-systray -x 19.0M 23.3M 0B 40.7M 3830 user /usr/bin/ibus-daemon --daemoni 19.0M 19.0M 0B 21.4M 20529 user /opt/sublime_text/plugin_host 19.9M 20.1M 0B 22.0M 3990 user nautilus -n 20.6M 29.9M 0B 50.2M 3898 user /usr/lib/unity/unity-panel-ser 27.1M 27.9M 0B 37.7M [...]
Пример представляет собой клон утилиты pmap
в Linux.
import sys import psutil from psutil._common import bytes2human from psutil._compat import get_terminal_size def safe_print(s): s = s[:get_terminal_size()[0]] try: print(s) except UnicodeEncodeError: print(s.encode('ascii', 'ignore').decode()) def main(): if len(sys.argv) != 2: sys.exit('usage: pmap <pid>') p = psutil.Process(int(sys.argv[1])) templ = "%-20s %10s %-7s %s" print(templ % ("Address", "RSS", "Mode", "Mapping")) total_rss = 0 for m in p.memory_maps(grouped=False): total_rss += m.rss safe_print(templ % ( m.addr.split('-')[0].zfill(16), bytes2human(m.rss), m.perms, m.path)) print("-" * 31) print(templ % ("Total", bytes2human(total_rss), '', '')) safe_print("PID = %s, name = %s" % (p.pid, p.name())) if __name__ == '__main__': main()
Вывод сценария:
$ python3 test.py 32402 Address RSS Mode Mapping 0000000000400000 1200K r-xp /usr/bin/python3.10 0000000000838000 4K r--p /usr/bin/python3.10 0000000000839000 304K rw-p /usr/bin/python3.10 00000000008ae000 68K rw-p [anon] 000000000275e000 5396K rw-p [heap] 00002b29bb1e0000 124K r-xp /lib/x86_64-linux-gnu/ld-2.17.so 00002b29bb203000 8K rw-p [anon] [...]
import argparse import datetime import socket import sys import psutil from psutil._common import bytes2human ACCESS_DENIED = '' NON_VERBOSE_ITERATIONS = 4 RLIMITS_MAP = { "RLIMIT_AS": "virtualmem", "RLIMIT_CORE": "coredumpsize", "RLIMIT_CPU": "cputime", "RLIMIT_DATA": "datasize", "RLIMIT_FSIZE": "filesize", "RLIMIT_MEMLOCK": "memlock", "RLIMIT_MSGQUEUE": "msgqueue", "RLIMIT_NICE": "nice", "RLIMIT_NOFILE": "openfiles", "RLIMIT_NPROC": "maxprocesses", "RLIMIT_NPTS": "pseudoterms", "RLIMIT_RSS": "rss", "RLIMIT_RTPRIO": "realtimeprio", "RLIMIT_RTTIME": "rtimesched", "RLIMIT_SBSIZE": "sockbufsize", "RLIMIT_SIGPENDING": "sigspending", "RLIMIT_STACK": "stack", "RLIMIT_SWAP": "swapuse", } def print_(a, b): if sys.stdout.isatty() and psutil.POSIX: fmt = '\x1b[1;32m%-13s\x1b[0m %s' % (a, b) else: fmt = '%-11s %s' % (a, b) print(fmt) def str_ntuple(nt, convert_bytes=False): if nt == ACCESS_DENIED: return "" if not convert_bytes: return ", ".join(["%s=%s" % (x, getattr(nt, x)) for x in nt._fields]) else: return ", ".join(["%s=%s" % (x, bytes2human(getattr(nt, x))) for x in nt._fields]) def run(pid, verbose=False): try: proc = psutil.Process(pid) pinfo = proc.as_dict(ad_value=ACCESS_DENIED) except psutil.NoSuchProcess as err: sys.exit(str(err)) # collect other proc info with proc.oneshot(): try: parent = proc.parent() if parent: parent = '(%s)' % parent.name() else: parent = '' except psutil.Error: parent = '' try: pinfo['children'] = proc.children() except psutil.Error: pinfo['children'] = [] if pinfo['create_time']: started = datetime.datetime.fromtimestamp( pinfo['create_time']).strftime('%Y-%m-%d %H:%M') else: started = ACCESS_DENIED print_('pid', pinfo['pid']) print_('name', pinfo['name']) print_('parent', '%s %s' % (pinfo['ppid'], parent)) print_('exe', pinfo['exe']) print_('cwd', pinfo['cwd']) print_('cmdline', ' '.join(pinfo['cmdline'])) print_('started', started) cpu_tot_time = datetime.timedelta(seconds=sum(pinfo['cpu_times'])) cpu_tot_time = "%s:%s.%s" % ( cpu_tot_time.seconds // 60 % 60, str((cpu_tot_time.seconds % 60)).zfill(2), str(cpu_tot_time.microseconds)[:2]) print_('cpu-tspent', cpu_tot_time) print_('cpu-times', str_ntuple(pinfo['cpu_times'])) if hasattr(proc, "cpu_affinity"): print_("cpu-affinity", pinfo["cpu_affinity"]) if hasattr(proc, "cpu_num"): print_("cpu-num", pinfo["cpu_num"]) print_('memory', str_ntuple(pinfo['memory_info'], convert_bytes=True)) print_('memory %', round(pinfo['memory_percent'], 2)) print_('user', pinfo['username']) if psutil.POSIX: print_('uids', str_ntuple(pinfo['uids'])) if psutil.POSIX: print_('uids', str_ntuple(pinfo['uids'])) if psutil.POSIX: print_('terminal', pinfo['terminal'] or '') print_('status', pinfo['status']) print_('nice', pinfo['nice']) if hasattr(proc, "ionice"): try: ionice = proc.ionice() except psutil.Error: pass else: if psutil.WINDOWS: print_("ionice", ionice) else: print_("ionice", "class=%s, value=%s" % ( str(ionice.ioclass), ionice.value)) print_('num-threads', pinfo['num_threads']) if psutil.POSIX: print_('num-fds', pinfo['num_fds']) if psutil.WINDOWS: print_('num-handles', pinfo['num_handles']) if 'io_counters' in pinfo: print_('I/O', str_ntuple(pinfo['io_counters'], convert_bytes=True)) if 'num_ctx_switches' in pinfo: print_("ctx-switches", str_ntuple(pinfo['num_ctx_switches'])) if pinfo['children']: template = "%-6s %s" print_("children", template % ("PID", "NAME")) for child in pinfo['children']: try: print_('', template % (child.pid, child.name())) except psutil.AccessDenied: print_('', template % (child.pid, "")) except psutil.NoSuchProcess: pass if pinfo['open_files']: print_('open-files', 'PATH') for i, file in enumerate(pinfo['open_files']): if not verbose and i >= NON_VERBOSE_ITERATIONS: print_("", "[...]") break print_('', file.path) else: print_('open-files', '') if pinfo['connections']: template = '%-5s %-25s %-25s %s' print_('connections', template % ('PROTO', 'LOCAL ADDR', 'REMOTE ADDR', 'STATUS')) for conn in pinfo['connections']: if conn.type == socket.SOCK_STREAM: type = 'TCP' elif conn.type == socket.SOCK_DGRAM: type = 'UDP' else: type = 'UNIX' lip, lport = conn.laddr if not conn.raddr: rip, rport = '*', '*' else: rip, rport = conn.raddr print_('', template % ( type, "%s:%s" % (lip, lport), "%s:%s" % (rip, rport), conn.status)) else: print_('connections', '') if pinfo['threads'] and len(pinfo['threads']) > 1: template = "%-5s %12s %12s" print_('threads', template % ("TID", "USER", "SYSTEM")) for i, thread in enumerate(pinfo['threads']): if not verbose and i >= NON_VERBOSE_ITERATIONS: print_("", "[...]") break print_('', template % thread) print_('', "total=%s" % len(pinfo['threads'])) else: print_('threads', '') if hasattr(proc, "rlimit"): res_names = [x for x in dir(psutil) if x.startswith("RLIMIT")] resources = [] for res_name in res_names: try: soft, hard = proc.rlimit(getattr(psutil, res_name)) except psutil.AccessDenied: pass else: resources.append((res_name, soft, hard)) if resources: template = "%-12s %15s %15s" print_("res-limits", template % ("RLIMIT", "SOFT", "HARD")) for res_name, soft, hard in resources: if soft == psutil.RLIM_INFINITY: soft = "infinity" if hard == psutil.RLIM_INFINITY: hard = "infinity" print_('', template % ( RLIMITS_MAP.get(res_name, res_name), soft, hard)) if hasattr(proc, "environ") and pinfo['environ']: template = "%-25s %s" print_("environ", template % ("NAME", "VALUE")) for i, k in enumerate(sorted(pinfo['environ'])): if not verbose and i >= NON_VERBOSE_ITERATIONS: print_("", "[...]") break print_("", template % (k, pinfo['environ'][k])) if pinfo.get('memory_maps', None): template = "%-8s %s" print_("mem-maps", template % ("RSS", "PATH")) maps = sorted(pinfo['memory_maps'], key=lambda x: x.rss, reverse=True) for i, region in enumerate(maps): if not verbose and i >= NON_VERBOSE_ITERATIONS: print_("", "[...]") break print_("", template % (bytes2human(region.rss), region.path)) if __name__ == '__main__': parser = argparse.ArgumentParser( description="печать информации о процессе") parser.add_argument("pid", type=int, help="process pid", nargs='?') parser.add_argument('--verbose', '-v', action='store_true', help="дополнительная информация") args = parser.parse_args() run(args.pid, args.verbose)
Использовать можно так $python3 test.py pid
. Если pid
не передан, то выводит подробную информацию о собственном процессе.
Вывод сценария:
$ python3 test.py pid 4600 name chrome parent 4554 (bash) exe /opt/google/chrome/chrome cwd /home/user cmdline /opt/google/chrome/chrome started 2016-09-19 11:12 cpu-tspent 27:27.68 cpu-times user=8914.32, system=3530.59, children_user=1.46, children_system=1.31 cpu-affinity [0, 1, 2, 3, 4, 5, 6, 7] memory rss=520.5M, vms=1.9G, shared=132.6M, text=95.0M, lib=0B, data=816.5M, dirty=0B memory % 3.26 user user uids real=1000, effective=1000, saved=1000 uids real=1000, effective=1000, saved=1000 [...] children PID NAME 4605 cat 4606 cat 4609 chrome 4669 chrome open-files PATH /opt/google/chrome/icudtl.dat /opt/google/chrome/snapshot_blob.bin /opt/google/chrome/natives_blob.bin /opt/google/chrome/chrome_100_percent.pak [...] connections PROTO LOCAL ADDR REMOTE ADDR STATUS UDP 10.0.0.3:3693 *:* NONE TCP 10.0.0.3:55102 172.217.22.14:443 ESTABLISHED UDP 10.0.0.3:35172 *:* NONE TCP 10.0.0.3:32922 172.217.16.163:443 ESTABLISHED [...] threads TID USER SYSTEM 11795 0.7 1.35 11796 0.68 1.37 15887 0.74 0.03 19055 0.77 0.01 [...] total=47 res-limits RLIMIT SOFT HARD virtualmem infinity infinity coredumpsize 0 infinity cputime infinity infinity datasize infinity infinity [...] mem-maps RSS PATH 381.4M [anon] 62.8M /opt/google/chrome/chrome 15.8M /home/user/.config/google-chrome/Default/History 6.6M /home/user/.config/google-chrome/Default/Favicons [...]