Python 映射器减速器

Python mapper reducer

我是 python 的新手,不明白为什么这段代码没有产生错误消息和输出。它读取网络日志文件。

def mapper(key, line):
    parts = line.split("/")
    if len(parts) > 2:
        return parts[1], 1
    return None, 1

def reducer(key, values):
    return key, sum(values)

def main():
    data = {key,values}
    with open('apache.log', 'r') as logfile:
        for idx, line in enumerate(logfile):
            line = line.strip()
            key, val = mapper(idx, line)
            if key in data:
                data[key].append(val)
            else:
                data[key] = [val,]
        for key, values in data.items():
            print reducer(key, values)

日志文件:

[31/Dec/1994:23:46:48 -0700] "GET 116.gif HTTP/1.0" 200 12053
remote - - [31/Dec/1994:23:50:42 -0700] "GET 2196.ps HTTP/1.0" 200 73941
remote - - [31/Dec/1994:23:55:08 -0700] "GET 45.html HTTP/1.0" 200 5489
remote - - [31/Dec/1994:23:56:55 -0700] "GET 2195.ps HTTP/1.0" 200 522318
remote - - [31/Dec/1994:23:59:37 -0700] "GET 957.ps HTTP/1.0" 200 122146
remote - - [01/Jan/1995:00:31:54 -0700] "GET index.html HTTP/1.0" 200 2797
remote - - [01/Jan/1995:00:31:58 -0700] "GET 2.gif HTTP/1.0" 200 2555

添加

main()

或更正式:

if __name__ == '__main__':
    main()

在源代码的末尾,然后再次 运行。

正如 flycee 所指出的,您似乎不是 运行 这段代码。 (或者你只是没有 post 调用 main?)

你还有其他问题...main第一行:

data = {key,values}

您显然希望 data 成为字典,因此逗号应该是冒号:{key: values}.

一个更大的问题是集合/字典中的两个变量--- keyvalues --- 还没有被定义。如果它被执行,这将引发 UnboundLocalError

其他问题...

  • main 中,您将 idx 设置为日志文件的行号(从 0 开始索引),并将其作为 [=15] 传递给 mapper =] 参数。 mapper 从不 使用 key 参数,因此您实际上是在创建 idx 值只是为了将其丢弃。

  • reducer 同样没有使用它的 key 参数,但至少它没有完全丢弃它。不过,没有理由将 mainkey 喂给 reducer 只是为了让它保持不变。

  • mapper returns a None 稍后将用作字典中的键,否则仅使用字符串作为键。 return 一个空字符串 ("") 代替 None,或者 --- 更好的是 --- 确保 return 值 is not None 之前将其添加到字典中。你说你想计算像 "May""Dec" 这样的月份...所以不要用所有非月份污染你的数据。

  • mapper returns 是两个值的元组,只有其中一个值是有用的。第二个值始终是 1,并且不可能是任何东西 1... 即使在 mapper 什么也找不到的情况下.所以只是 return 有趣的部分:字符串 "Jan""Oct" 或其他。

  • 当您事先知道每个元素都是 1 时,在包含数万个元素的列表上使用 sum 就有点过分了。请改用 len

  • 当您事先知道该列表存在时,

  • 在包含数万个元素的列表上使用 len 就有点矫枉过正了 只是 来计算一些东西.使用一个 int 代替。

  • 当 Python 标准库已经免费为您提供一个计数器时,从几个不同的函数中实现一个计数器就太过分了。请改用 collections.Counter

最后的狡辩:您的 mapper 并没有真正映射任何东西,您的 reducer 中唯一减少的是内置的 sum 函数。那么为什么不调用 mapper 更有意义的东西,比如 month_logged,并将 reducer 完全替换为 sum