我使用regex查看文件以检查用户名及其操作是否导致错误(error表示错误,INFO表示成功操作)我使用一个嵌套的字典来跟踪操作,用户名作为主键和嵌套的字典有多少INFO和ERROR行他们生成。
#!/usr/bin/env python3
import re
users = {}
with open('logfile.txt') as f:
for line in f:
regex_user = r"(INFO|ERROR): .* ((.+))$"
"""searches for users and if there message was info or error"""
user = re.serach(regex_user, line)
if user is None:
continue
name = user[2]
cat = user[1]
try:
# Method 1?
users[name][cat] = users[name].get(cat, 0) + 1
# Method 2?
users[name][cat] = users.get(name, {}).get(cat, 0) + 1
except KeyError:
print("Where are my keys?")
我想知道这两种方法中的哪一种(如果有的话)正确地修改了字典以增加各自嵌套键的计数。
输出如下所示:
{'John': {'INFO': 22, 'ERROR': 3}}
如果日志中包含22行INFO和3行ERROR,
您可能想用嵌套的collections.defaultdict
或使用setdefault()
来解决这个问题,尽管在我看来后者不是一个干净的。collections.defaultdict()
将允许您引用尚未存在的字典键,这是您的问题的关键。
试试这样写:
import collections
import json
import random
users = collections.defaultdict(lambda: collections.defaultdict(int))
for i in range(100):
user = random.choice(["John", "Jane", "Sanjay"])
cat = random.choice(["INFO", "ERROR"])
users[user][cat] += 1
print(json.dumps(users, indent=2))
将输出如下内容:
{
"Jane": {
"INFO": 16,
"ERROR": 19
},
"John": {
"ERROR": 21,
"INFO": 10
},
"Sanjay": {
"INFO": 18,
"ERROR": 16
}
}
尽管每次运行都会有所不同。
正如@Ryukashin所指出的,defaultdict()
不像dict()
那样好地完成print()
。因此,如果出于某种原因确实需要的话,倒投是可能的。最简单(但不是最有效)的方式可能是:
users = json.loads(json.dumps(users))