请在回答之前阅读整个问题,因为它不是您的想法......我正在考虑创建代表系统上硬件设备的python对象包装器(下面的修剪示例)。
class TPM(object):
@property
def attr1(self):
"""
Protects value from being accidentally modified after
constructor is called.
"""
return self._attr1
def __init__(self, attr1, ...):
self._attr1 = attr1
...
@classmethod
def scan(cls):
"""Calls Popen, parses to dict, and passes **dict to constructor"""
大多数构造函数输入涉及在subprocess.Popen中运行命令行输出,然后解析输出以填充对象属性。我已经提出了几种方法来处理这些问题,但我对我刚刚放在一起并试图找到更好的解决方案感到不满意。以下是我发现的常见捕获量。 (快速注意:工具版本受到严格控制,因此解析后的输出不会意外更改。)
许多工具产生变体输出,有时包括字段,有时不包括字段。这意味着如果你组装一个dict来包装在一个容器对象中,那么构造函数或多或少地被迫接受** kwargs并且没有真正定义的字段。我不喜欢这样,因为它通过pylint等进行静态分析并不是很有用。我更喜欢定义的界面,以便狮身人面像文档更清晰,并且可以更可靠地检测错误。
除了** kwargs之外,我还尝试将许多字段的默认args设置为None,最终结果非常难看。我不喜欢这个选项的一件事是可选字段总是不在命令行工具输出的末尾。这使得查看构造函数并将其与工具输出相匹配有点令人费解。
我非常希望避免首先构建字典,但使用setattr创建属性会使pylint无法检测_attr1等等并创建警告。欢迎任何想法......
基本上,我正在寻找合适的Pythonic方法来做到这一点。我的要求,重新总结如下:
在Python中有没有一种很好的方法(希望没有大量的样板代码)?如果是这样,它是什么?
编辑:
根据一些澄清请求,我们可以看一下tpm_version命令。这是我的笔记本电脑的输出,但对于这个TPM,它并没有包含所有可能的属性。有时,该命令将返回我还想捕获的额外属性。这使得解析容器对象上的已知属性名称相当困难。
TPM 1.2 Version Info:
Chip Version: 1.2.4.40
Spec Level: 2
Errata Revision: 3
TPM Vendor ID: IFX
Vendor Specific data: 04280077 0074706d 3631ffff ff
TPM Version: 01010000
Manufacturer Info: 49465800
示例代码(请忽略缺乏完整性检查,为简洁而修剪):
def __init__(self, chip_version, spec_level, errata_revision,
tpm_vendor_id, vendor_specific_data, tpm_version,
manufacturer_info):
self._chip_version = chip_version
...
@classmethod
def scan(cls):
tpm_proc = Popen("/usr/sbin/tpm_version")
stdout, stderr = Popen.communicate()
tpm_dict = dict()
for line in tpm_proc.stdout.splitlines():
if "Version Info:" in line:
pass
else:
split_line = line.split(":")
attribute_name = (
split_line[0].strip().replace(' ', '_').lower())
tpm_dict[attribute_name] = split_line[1].strip()
return cls(**tpm_dict)
这里的问题是这个(或者我可能无法查看获取每个可能字段的来源的另一个)可能会添加额外的东西,导致我的解析器工作,但我的对象是不捕获字段。这就是我真正想要以优雅的方式解决的问题。
答案 0 :(得分:0)
在过去的几个月里,我一直在为这个问题做出更加坚实的答案,因为我基本上在硬件支持库上工作,并且最终得到了一个令人满意的(虽然非常详细)答案。