Seite 1 von 1

Informationen aus /proc/$$/status lesen...

Verfasst: Donnerstag 18. August 2011, 09:08
von jens
Kleines Codestückchen um die Informationen aus /proc/$$/status in verarbeitbarer Form zu erhalten.

So erhält man u.a. die aktuelle Speichernutzung eines Prozesses...

Ich erstelle bewusst nicht direkt ein dict, sondern liefere ein tuple zurück, weil man so die original Reihenfolge erhält und man das schnell mit dict() umwandeln kann, siehe unten.

btw. das wird was für: http://www.python-forum.de/viewtopic.php?f=6&t=27168

Verbesserungsvorschläge?

Code: Alles auswählen

from __future__ import with_statement # for Python 2.5

def process_information(pid=None):
    """
    Get process information.

    If pid == None: We use "self" to get the current process information.
    
    Note:
      * Will only work if /proc/$$/status exists (where $$ is the given pid).
      * We don't cache the error, if /proc/$$/status doesn't exists!
      * All values convert to integers (kB values convertet to bytes)
   
    returns a tuple, which can be easy convert info a dict, e.g.:

    try:
        p = dict(process_information())
    except IOError, err:
        print "Error: %s" % err
    else:
        print "Peak virtual memory size: %i Bytes" % p["VmPeak"]
    """
    if pid is None:
        pid = "self"
    path = "/proc/%s/status" % pid

    result = []
    with open(path, "r") as f:
        for line in f:
            key, values = [i.strip() for i in line.split(":",1)]
            if "\t" in values:
                values2 = values.split("\t")
            else:
                values2 = values.split(" ")

            length = len(values2)
            if length == 1:
                if len(values)==16:
                    result.append((key, values))
                else:
                    try:
                        result.append((key, int(values)))
                    except ValueError, err:
                        result.append((key, values))
                continue
            elif length == 2:
                if values2[1].lower()=="kb":
                    result.append((key, int(values2[0])*1024))
                    continue

            try:
                result.append((key, [int(v) for v in values2]))
            except ValueError:
                result.append((key, values))

    return tuple(result)
Beispiel:

Code: Alles auswählen

import pprint
m = memory_usage()
pprint.pprint(m)
Ausgabe:

Code: Alles auswählen

(('Name', 'python'),
 ('State', 'R (running)'),
 ('Tgid', 3381),
 ('Pid', 3381),
 ('PPid', 3380),
 ('TracerPid', 0),
 ('Uid', [1000, 1000, 1000, 1000]),
 ('Gid', [1000, 1000, 1000, 1000]),
 ('FDSize', 64),
 ('Groups', [4, 20, 24, 46, 112, 120, 122, 1000]),
 ('VmPeak', 35205120),
 ('VmSize', 35205120),
 ('VmLck', 0),
 ('VmHWM', 5160960),
 ('VmRSS', 5160960),
 ('VmData', 2740224),
 ('VmStk', 139264),
 ('VmExe', 2289664),
 ('VmLib', 4276224),
 ('VmPTE', 69632),
 ('VmSwap', 0),
 ('Threads', 1),
 ('SigQ', '0/16382'),
 ('SigPnd', '0000000000000000'),
 ('ShdPnd', '0000000000000000'),
 ('SigBlk', '0000000000000000'),
 ('SigIgn', '0000000001001000'),
 ('SigCgt', '0000000180000002'),
 ('CapInh', '0000000000000000'),
 ('CapPrm', '0000000000000000'),
 ('CapEff', '0000000000000000'),
 ('CapBnd', 'ffffffffffffffff'),
 ('Cpus_allowed', 3),
 ('Cpus_allowed_list', '0-1'),
 ('Mems_allowed', '00000000,00000001'),
 ('Mems_allowed_list', 0),
 ('voluntary_ctxt_switches', 0),
 ('nonvoluntary_ctxt_switches', 0))
bzw.:

Code: Alles auswählen

pprint.pprint(dict(m))
Ausgabe:

Code: Alles auswählen

{'CapBnd': 'ffffffffffffffff',
 'CapEff': '0000000000000000',
 'CapInh': '0000000000000000',
 'CapPrm': '0000000000000000',
 'Cpus_allowed': 3,
 'Cpus_allowed_list': '0-1',
 'FDSize': 64,
 'Gid': [1000, 1000, 1000, 1000],
 'Groups': [4, 20, 24, 46, 112, 120, 122, 1000],
 'Mems_allowed': '00000000,00000001',
 'Mems_allowed_list': 0,
 'Name': 'python',
 'PPid': 3380,
 'Pid': 3381,
 'ShdPnd': '0000000000000000',
 'SigBlk': '0000000000000000',
 'SigCgt': '0000000180000002',
 'SigIgn': '0000000001001000',
 'SigPnd': '0000000000000000',
 'SigQ': '0/16382',
 'State': 'R (running)',
 'Tgid': 3381,
 'Threads': 1,
 'TracerPid': 0,
 'Uid': [1000, 1000, 1000, 1000],
 'VmData': 2740224,
 'VmExe': 2289664,
 'VmHWM': 5160960,
 'VmLck': 0,
 'VmLib': 4276224,
 'VmPTE': 69632,
 'VmPeak': 35205120,
 'VmRSS': 5160960,
 'VmSize': 35205120,
 'VmStk': 139264,
 'VmSwap': 0,
 'nonvoluntary_ctxt_switches': 0,
 'voluntary_ctxt_switches': 0}

Re: Informationen aus /proc/self/status lesen...

Verfasst: Donnerstag 18. August 2011, 09:41
von BlackJack
@jens: Ich glaube im `open()` sollte `path` verwendet werden statt der literalen Zeichenkette.

Re: Informationen aus /proc/self/status lesen...

Verfasst: Donnerstag 18. August 2011, 09:50
von jens
Jup, copy&paste Fehler (habs oben korrigiert)... Ich hatte zuerst den pfad fest verdrahtet und später gemerkt das man auch mal eben irgendeine pid nehmen könnte ;)

Ach, wer sich eigentlich nur für "VmHWM" Interessiert, der kann eigentlich auch auf http://docs.python.org/library/resource.html zurück greifen, z.B.:

Code: Alles auswählen

import resource
d = dict(process_information())
self_rusage = resource.getrusage(resource.RUSAGE_SELF)

print 'Peak resident set size ("high water mark") / maximum resident set size:'
print "from proc: %s kBytes" % (d["VmHWM"]/1024.0)
print "from resource: %s kBytes" % (self_rusage.ru_maxrss)
Ausgaben, sehen ungefähr so aus:
Peak resident set size ("high water mark") / maximum resident set size:
from proc: 164072.0 kBytes
from resource: 164072 kBytes