我的Python for循环导致了MemoryError。我该如何进行优化?

4
我将尝试编制一个包含所有苹果设备MAC地址的列表。oui.txt告诉我,苹果已被分配了77个可用于使用的MAC地址范围。这些范围的形式为:
00:00:00
00:11:11
etc...

这让我有最后三个十六进制数字要添加。这是16^6,总计1291845632个苹果MAC地址。
我现在遇到的问题是编写一个程序来创建这些MAC地址的列表。以下是我的当前代码:
import re

apple_mac_range = []
apple_macs      = []

# Parse the HTML of http://standards.ieee.org/cgi-bin/ouisearch to get the MACs
with open('apple mac list', 'r') as f:
    for line in f.readlines():

        match = re.search(r'[\w\d]{2}-[\w\d]{2}-[\w\d]{2}', line)

        if match:
            apple_mac_range.append(match.group().split('-'))

for mac in apple_mac_range:
    for i in range(1, 1291845633):
        print i

我遇到了一个MemoryError的问题... 我该如何进行优化呢?


2
你到底为什么想要生成所有这些MAC地址的完整列表? - Jim Garrison
1
你为什么需要枚举十亿个地址?你真正想要解决的问题是什么? - SingleNegationElimination
嗯,我真的只想要iPhone设备的MAC地址,但是从我目前找到的资料来看,苹果似乎没有为特定设备使用特定的MAC地址范围。 - dave
1
这并没有回答问题。你为什么需要这些MAC地址?你为什么需要提前枚举它们?你打算用它们做什么? - Karl Knechtel
5个回答

18
< p > range(1, 1291845633) 会一次性创建包含 1,291,845,632 个元素(数GB)的列表。建议使用 xrange(1, 1291845633) ,这样它只会在需要时生成元素,而不是一次性全部创建。

无论如何,看起来你想要更类似于这样的东西:

for mac in apple_mac_range: 
    for i in xrange(16777216): 
        print mac, i 

当然,一个包含13亿个MAC地址的列表可能并不会很有用。如果你想要查看给定的MAC地址是否为苹果设备,只需检查前三个字节的前缀是否在77个列表中即可。如果您尝试通过向路由器或其他设备提供所有可能的MAC地址列表来进行访问控制,则该设备不太可能接受其列表中的13亿项。


3

其他人已经回答了你的实际问题,但我不确定这是否是所需的。为什么不创建一个实现 __contains__ 的类来对 MAC 地址进行算法测试呢?我假设你正在获取一个 MAC 地址,并且想要测试它是否可能是 iPhone 的 MAC 地址,因此你可以实现该类,然后只需要执行以下操作:

if found_mac in MACTester:
  ...do work...

如果你真的想要一个可迭代的序列,那么你至少应该使用生成器而不是试图将它们全部放入内存。


1
怎么样:
i = 0
while i < 1291845633:
  print i
  i += 1

1

不要使用readlines

with file('apple mac list') as f:
    for x in f:
        print x

0
首先,range(1, 1291845633) 创建了一个包含大约十亿个条目的列表。由于每个条目至少是 sizeof(Py_Object),所以你很容易就会耗尽内存,这并不奇怪。不要这样做。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接