【问题标题】:Is there a python module to parse Linux's sysfs?是否有 python 模块来解析 Linux 的 sysfs?
【发布时间】:2011-06-06 15:14:07
【问题描述】:

大家好,Linux 在 procfssysfs 中有很多很棒的功能,而像 vmstat 这样的工具扩展了很多功能,但是我需要从各种这些系统中收集数据并且是希望利用统一的 Python 实用程序,而不是将一堆不同的脚本拼凑在一起。

为了做到这一点,我首先需要确定 Python 是否具有我需要充分解析/处理不同数据收集点的点点滴滴。所以,我的问题的本质:

是否已经有处理/解析sysfs 对象的python 模块?

我已经通过 Google、usenet 和各种论坛寻找这样的野兽,但我还没有找到任何智能或实用的东西。所以,在我切出一个之前,我想我先在这里检查一下。

【问题讨论】:

标签: python linux internals


【解决方案1】:

不太清楚为什么需要特定的东西,它们大部分都是文本文件,你可以直接弄乱它们。
据我所知,没有任何 python 模块可以做到这一点。

【讨论】:

  • 呃?这样一个模块的重点是适应以结构化方式读取文件......即 sysfs.thermal_zone0.temp
【解决方案2】:

试试这个:

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)

它没有以任何方式打磨,但 IIRC 可以工作 :)

【讨论】:

  • 如何使用这个?找出类似以下的内容,例如,numa 节点?
    SysFsObject sysfs print sysfs.devices.0000:80:00.0.numa_node
  • (为未格式化的 python 道歉;cmets 中缺少嵌入的换行符使得无法在评论中编写 python 代码)
  • 对于这样的东西,你必须使用 getattr: getattr(sysfs.devices, "0000:80:00.0").numa_node。 Python 既不允许 . and : 标识符中也不以数字开头。
  • 不幸的是,这些实现似乎都没有处理 sysfs 文件的形式,这些文件总是返回几个选项,所选选项在括号中。我使用这样的东西来读取 sysfs 值。附言你到底应该如何在评论中提供代码 sn-p ? def sysfs_read(path): f = open(path, "r") text = f.read() f.close() text = text.strip() if not "[" in text: 返回文本垃圾,after_first_bracket = text .split('[') 值,垃圾 = after_first_bracket.split(']') 返回值```
【解决方案3】:

来自电影人的回答,但删除了 int() 演员:

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)

任意转换为 int 是出乎意料的,甚至是危险的。例如,如果您要在 sysfs 中流行的任何 cpulist 文件上使用该代码,则在多处理器系统上将始终返回诸如“0-7”之类的字符串。然后有一天,有人在单核系统上使用您的代码并读取现在包含“0”的完全相同的 sysfs 文件返回一个 int。

换句话说,任何调用该代码并期望接收 sysfs 的本机数据类型(字符串)的函数都必须显式转换为 str()。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-09
  • 1970-01-01
  • 2011-01-08
  • 2010-09-26
  • 2013-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多