Разделение вывода ps с помощью Python - PullRequest
10 голосов
/ 25 марта 2009

В Linux команда ps aux выводит список процессов с несколькими столбцами для каждой статистики. например,

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
...
postfix  22611  0.0  0.2  54136  2544 ?        S    15:26   0:00 pickup -l -t fifo -u
apache   22920  0.0  1.5 198340 16588 ?        S    09:58   0:05 /usr/sbin/httpd

Я хочу иметь возможность прочитать это при использовании Python и разделить каждую строку, а затем каждый столбец, чтобы их можно было использовать в качестве значений.

В большинстве случаев это не проблема:

ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]
processes = ps.split('\n')

Теперь я могу перебирать процессы, чтобы получить каждую строку и разделить ее на пробелы, например

sep = re.compile('[\s]+')
for row in processes:
    print sep.split(row)

Однако проблема в том, что в последнем столбце команды иногда есть пробелы. В приведенном выше примере это можно увидеть в команде

pickup -l -t fifo -u

который будет разделен как

['postfix', '22611', '0.0', '0.2', '54136', '2544', '?', 'S', '15:26', '0:00', 'pickup', '-l', '-t', 'fifo', '-u']

но я действительно хочу это как:

['postfix', '22611', '0.0', '0.2', '54136', '2544', '?', 'S', '15:26', '0:00', 'pickup -l -t fifo -u']

Итак, мой вопрос: как я могу разделить столбцы, но когда дело доходит до командного столбца, сохранить всю строку как один элемент списка, а не разделять пробелами?

Ответы [ 5 ]

22 голосов
/ 25 марта 2009

Используйте второй параметр для split, который определяет максимальное количество полей, на которые нужно разбить строку. Я думаю, вы можете найти число, посчитав количество полей в первой строке, то есть заголовки столбцов.

ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]
processes = ps.split('\n')
# this specifies the number of splits, so the splitted lines
# will have (nfields+1) elements
nfields = len(processes[0].split()) - 1
for row in processes[1:]:
    print row.split(None, nfields)
13 голосов
/ 30 июля 2010

Проверьте пакет python.psutils .

psutil.process_iter возвращает генератор, который вы можете использовать для перебора всех процессов. p.cmdline - это список аргументов cmdline каждого объекта Process, разделенных так, как вы хотите.

Вы можете создать словарь pids vs (pid,cmdline,path), используя всего одну строку, а затем использовать его в любом месте.

pid_dict = dict([(p.pid, dict([('pid',p.pid), ('cmdline',p.cmdline), ('path',p.path)]))
                 for p in psutil.process_iter()]))
4 голосов
/ 25 марта 2009

Почему бы вам не использовать PSI вместо этого? PSI предоставляет информацию о процессах в Linux и других вариантах Unix.

import psi.process
for p in psi.process.ProcessTable().values(): …
1 голос
/ 08 мая 2012

Вот хорошая рутина и использование, чтобы вы начали:

def getProcessData():
    ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]
    processes = ps.split('\n')
    # this specifies the number of splits, so the splitted lines
    # will have (nfields+1) elements
    nfields = len(processes[0].split()) - 1
    retval = []
    for row in processes[1:]:
        retval.append(row.split(None, nfields))
    return retval

wantpid = int(contents[0])
pstats = getProcessData()
for ps in pstats:
    if (not len(ps) >= 1): continue
    if (int(ps[1]) == wantpid):
        print "process data:"
        print "USER              PID       %CPU        %MEM       VSZ        RSS        TTY       STAT      START TIME      COMMAND"
        print "%-10.10s %10.10s %10.10s %10.10s %10.10s %10.10s %10.10s %10.10s %10.10s  %s" % (ps[0], ps[1], ps[2], ps[3], ps[4], ps[5], ps[6], ps[7], ps[8], ps[9])
1 голос
/ 25 марта 2009

Необязательный аргумент maxsplit для метода split может помочь вам:

sep.split.(row, maxsplit=42)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...