我的Python for循环导致MemoryError,如何优化?

4 投票
5 回答
4492 浏览
提问于 2025-04-16 08:19

我正在尝试列出所有苹果设备可能使用的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错误……我该怎么优化它呢?

5 个回答

1

这样怎么样:

i = 0
while i < 1291845633:
  print i
  i += 1
3

其他人已经回答了你的实际问题,但我不太确定这是否是你真正需要的。为什么不创建一个类,里面实现__contains__方法来算法上测试MAC地址呢?我猜你是想获取一个MAC地址,然后想判断它是否可能是iPhone的MAC地址,所以你可以实现这个类,然后就可以像这样做:

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

另外,如果你真的想要一个可迭代的序列,至少应该使用生成器,而不是试图把所有数据都放到内存里。

18

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 

当然,拥有一个包含1.3亿个MAC地址的列表可能并没有太大用处。如果你想检查某个MAC地址是否是苹果设备,只需要查看它的前3个字节是否在77个地址的列表中就可以了。如果你是想通过给路由器或其他设备提供一个所有可能的MAC地址的列表来进行访问控制,那设备很可能无法接受1.3亿个项目的列表。

撰写回答