开发者

Is there a python module to parse Linux's sysfs?

开发者 https://www.devze.com 2023-02-04 12:11 出处:网络
Hey all, Linux has a lot of great features in procfs and sysfs, and tools like vmstat extend that quite a bit, but I have a need to collect data from a variety of these systems and was hoping to l开发

Hey all, Linux has a lot of great features in procfs and sysfs, and tools like vmstat extend that quite a bit, but I have a need to collect data from a variety of these systems and was hoping to l开发者_运维知识库everage a unified Python utility instead of hacking together a bunch of disparate scripts.

In order to do that I first need to identify whether or not Python has the bits and pieces I need to adequately parse/process the different data collection points. So, the essence of my question:

Is there a python module that handles/parses the sysfs objects already?

I've looked for such a beast via Google, usenet, and various forums, but I haven't yet found anything intelligent or functional. So, before I carve one out, I figured I'd check here first.


Try this one:

from os import listdir
from os.path import isdir, isfile, islink, join, realpath, normpath
from keyword import iskeyword

_norm = lambda name: name + ('_' if iskeyword(name) else '')

def _denorm(name):
    if name.endswith('_') and iskeyword(name[:-1]):
        return name[:-1]
    else:
        return name

def _norm_path(path):
    return normpath(realpath(path))

class SysFsObject(object):
    __slots__ = ['_path', '__dict__']

    @staticmethod
    def __id_args__(path='/sys'):
        return _norm_path(path)

    def __init__(self, path='/sys'):
        self._path = _norm_path(path)
        if not self._path.startswith('/sys'):
            raise RuntimeError("Using this on non-sysfs files is dangerous!")
        self.__dict__.update(dict.fromkeys(_norm(i) for i in listdir(self._path)))

    def __repr__(self):
        return "<SysFsObject %s>" % self._path

    def __setattr__(self, name, val):
        if name.startswith('_'):
            return object.__setattr__(self, name, val)

        name = _denorm(name)

        p = realpath(join(self._path, name))
        if isfile(p):
            file(p, 'w').write(str(val))
        else:
            raise RuntimeError

    def __getattribute__(self, name):
        if name.startswith('_'):
            return object.__getattribute__(self, name)

        name = _denorm(name)

        p = realpath(join(self._path, name))
        if isfile(p):
            data = open(p, 'r').read()[:-1]
            try:
                return int(data)
            except ValueError:
                return data
        elif isdir(p):
            return SysFsObject(p)

It's not polished in any way, but IIRC it works :)


From filmor's answer, but with the int() casting removed:

from os import listdir
from os.path import isdir, isfile, islink, join, realpath, normpath
from keyword import iskeyword

_norm = lambda name: name + ('_' if iskeyword(name) else '')

def _denorm(name):
    if name.endswith('_') and iskeyword(name[:-1]):
        return name[:-1]
    else:
        return name

def _norm_path(path):
    return normpath(realpath(path))

class SysFsObject(object):
    __slots__ = ['_path', '__dict__']

    @staticmethod
    def __id_args__(path='/sys'):
        return _norm_path(path)

    def __init__(self, path='/sys'):
        self._path = _norm_path(path)
        if not self._path.startswith('/sys'):
            raise RuntimeError("Using this on non-sysfs files is dangerous!")
        self.__dict__.update(dict.fromkeys(_norm(i) for i in listdir(self._path)))

    def __repr__(self):
        return "<SysFsObject %s>" % self._path

    def __setattr__(self, name, val):
        if name.startswith('_'):
            return object.__setattr__(self, name, val)

        name = _denorm(name)

        p = realpath(join(self._path, name))
        if isfile(p):
            file(p, 'w').write(val)
        else:
            raise RuntimeError

    def __getattribute__(self, name):
        if name.startswith('_'):
            return object.__getattribute__(self, name)

        name = _denorm(name)

        p = realpath(join(self._path, name))
        if isfile(p):
            return open(p, 'r').read()[:-1]
        elif isdir(p):
            return SysFsObject(p)

Arbitrarily casting to int is unexpected and even dangerous. For example, if you were to use that code on any of the cpulist files prevalent in sysfs, a string such as "0-7" would always be returned on multi-processor systems. Then someday, someone uses your code on a single-core system and reading the exact same sysfs file that now contains "0" returns an int.

In other words, any function that calls that code and expects to receive the native data type of sysfs (strings) must explicitly cast to str().


Not really sure why you need something specific, they are all text files for the most part, you can just mess with them directly.
There aren't any python modules that does that as far as I know.

0

精彩评论

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

关注公众号