我正在try 以 struct 化的方式捕获(S3)日志(log).我正在使用这种类型的元组捕获与访问相关的元素:

class _Access(NamedTuple):
    time: datetime
    ip: str
    actor: str
    request_id: str
    action: str
    key: str
    request_uri: str
    status: int
    error_code: str

然后,我有一个使用这个命名元组的类,如下所示(仅编辑到相关代码):

class Logs:
    def __init__(self, log: str):
        raw_logs = match(S3_LOG_REGEX, log)
        if raw_logs is None:
            raise FormatError(log)
        logs = raw_logs.groups()
        timestamp = datetime.strptime(logs[2], "%d/%b/%Y:%H:%M:%S %z")
        http_status = int(logs[9])
        access = _Access(
            timestamp,
            logs[3],
            logs[4],
            logs[5],
            logs[6],
            logs[7],
            logs[8],
            http_status,
            logs[10],
        )
        self.access = access

问题是,当我现在想使用它时,它太冗长了:

>>> log_struct = Logs(raw_log)
>>> log_struct.access.action # I don't want to have to add `access`

正如我在上面提到的,我更愿意做这样的事情:

>>> log_struct = Logs(raw_log)
>>> log_struct.action

但我仍然希望将这个干净的命名元组命名为_Access.我如何才能使从access开始的所有内容都在顶层可用?

具体地说,我有这样一句话:

        self.access = access

这让我多了一层我不想要的"层".我希望能够以某种方式"解开"它,就像我们可以通过传递*args个星号来解开论点一样.但我不确定在这种情况下如何解包元组.

推荐答案

对于您的用例,您真正需要的是NamedTuple子类的替代构造函数,用于将日志(log)条目的字符串解析到各自的字段中,这可以通过创建一个类方法来实现,该类方法使用从输入字符串解析的参数调用__new__方法.

仅使用字段ipaction作为简化示例:

from typing import NamedTuple

class Logs(NamedTuple):
    ip: str
    action: str

    @classmethod
    def parse(cls, log: str) -> 'Logs':
        return cls.__new__(cls, *log.split())

log_struct  = Logs.parse('192.168.1.1 GET')
print(log_struct)
print(log_struct.ip)
print(log_struct.action)

这会产生以下结果:

Logs(ip='192.168.1.1', action='GET')
192.168.1.1
GET

Python相关问答推荐

使用plotnine和Python构建地块

DataFrame groupby函数从列返回数组而不是值

如何使用Python将工作表从一个Excel工作簿复制粘贴到另一个工作簿?

如何获取TFIDF Transformer中的值?

如何获取numpy数组的特定索引值?

driver. find_element无法通过class_name找到元素'""

有没有一种ONE—LINER的方法给一个框架的每一行一个由整数和字符串组成的唯一id?

多处理队列在与Forking http.server一起使用时随机跳过项目

在Python中使用if else或使用regex将二进制数据如111转换为001""

python sklearn ValueError:使用序列设置数组元素

循环浏览每个客户记录,以获取他们来自的第一个/最后一个渠道

关于两个表达式的区别

为什么Python内存中的列表大小与文档不匹配?

如何根据rame中的列值分别分组值

查看pandas字符列是否在字符串列中

Python—在嵌套列表中添加相同索引的元素,然后计算平均值

PySpark:如何最有效地读取不同列位置的多个CSV文件

python3中np. divide(x,y)和x/y有什么区别?'

无法使用请求模块从网页上抓取一些产品的名称

将Pandas DataFrame中的列名的长文本打断/换行为_STRING输出?