文件中列表项的条目
Entry of a list item in a file
下午好,我有多个 IP 列表和 MAC,任意长度的列表
A = [['10.0.0.1','00:4C:3S:**:**:**', 0], ['10.0.0.2', '00:5C:4S:**:**:**', 0], [....], [....]]
我想检查这个 MAC 是否在 oui 文件中:
E043DB (base 16) Shenzhen
2405f5 (base 16) Integrated
3CD92B (base 16) Hewlett Packard
...
如果列表中的 MAC 在文件中,则将制造商的名称写为 3 个列表项。我正在尝试这样做,结果只检查了第一个元素,其余的没有检查,我该怎么做请告诉我?
f = open('oui.txt', 'r')
for values in A:
for line in f.readlines():
if values[1][0:8].replace(':','') in line:
values[2]=(line.split('(base 16)')[1].strip())
f.close()
print (A)
并得到答案:
A = [['10.0.0.1','00:4C:3S:**:**:**', 'Firm Name'], ['10.0.0.2', '00:5C:4S:**:**:**', 0], [....], [....]]
问题是你的循环顺序颠倒了。通常这不是什么大问题,但是当工作对象被消耗时(如 IO 文件对象),内容将在迭代后不再产生。
您需要先迭代 lines
,然后在每个 lines
中迭代 A
以检查值:
with open('oui.txt', 'r') as f:
for line in f.readlines():
for values in A:
if values[1][0:8].replace(':','') in line:
values[2]=(line.split('(base 16)')[1].strip())
print (A)
请注意,我将您的文件打开更改为使用 with
context manager,一旦您的代码存在 with
块,它将自动为您 close()
文件。建议手动 open
编辑文件,因为之后您可能会忘记 close()
它。
问题
考虑您代码的 "shape":
f = open('a file')
for values in [ 'some list' ]:
for line in f.readlines():
您的两个循环正在执行此操作:
Start with first value in list
Read all lines remaining in file object f
Move to next value in list
Read all lines remaining in file object f
除了你第一次告诉它 "read all lines remaining" 它会这样做。
所以,除非你有办法将更多行放入 f(这可能发生在像 stdin 这样的异步文件中!)你将 "good" 遍历文件,然后每次后续遍历文件对象将指向文件的末尾,所以你什么也得不到。
一个解决方案
当您处理一个文件时,您希望只处理一次。与其他操作相比,文件 I/O 的开销很大。所以你可以选择 (a) 将整个文件读入内存,然后做任何你想做的事,因为它不再是一个文件;或 (b) 只扫描一次。
如果您选择只扫描一次,简单的解决方案就是反转两个 for 循环。而不是这样做:
for item in list:
for line in file:
改为这样做:
for line in file:
for item in list:
很快!您现在只读取文件一次。
其他注意事项
如果我查看您的代码和示例,您似乎正在尝试对特定键进行 完全匹配 。您 trim 在您的列表中找到 MAC 地址,以根据制造商 ID 核对它们。
这向我表明,您拥有的 列表值(来源 MAC 地址)可能 多得多 。因此,也许您应该考虑将图块的内容读入内存,而不是一次处理一行。
将文件存入内存后,考虑构建一个合适的字典。您有一个键(MAC 前缀)和一个值(制造商)。所以构建类似:
for line in f:
mac = line.split('(base 16)')[0].strip()
mfg = line.split('(base 16)')[1].strip()
mac_to_mfg[mac] = mfg
然后您可以遍历源地址并使用字典的 O(1) 查找对您有利:
for src in A:
prefix = src[1][:8].replace(':', '')
if prefix in mac_to_mfg:
# etc...
下午好,我有多个 IP 列表和 MAC,任意长度的列表
A = [['10.0.0.1','00:4C:3S:**:**:**', 0], ['10.0.0.2', '00:5C:4S:**:**:**', 0], [....], [....]]
我想检查这个 MAC 是否在 oui 文件中:
E043DB (base 16) Shenzhen
2405f5 (base 16) Integrated
3CD92B (base 16) Hewlett Packard
...
如果列表中的 MAC 在文件中,则将制造商的名称写为 3 个列表项。我正在尝试这样做,结果只检查了第一个元素,其余的没有检查,我该怎么做请告诉我?
f = open('oui.txt', 'r')
for values in A:
for line in f.readlines():
if values[1][0:8].replace(':','') in line:
values[2]=(line.split('(base 16)')[1].strip())
f.close()
print (A)
并得到答案:
A = [['10.0.0.1','00:4C:3S:**:**:**', 'Firm Name'], ['10.0.0.2', '00:5C:4S:**:**:**', 0], [....], [....]]
问题是你的循环顺序颠倒了。通常这不是什么大问题,但是当工作对象被消耗时(如 IO 文件对象),内容将在迭代后不再产生。
您需要先迭代 lines
,然后在每个 lines
中迭代 A
以检查值:
with open('oui.txt', 'r') as f:
for line in f.readlines():
for values in A:
if values[1][0:8].replace(':','') in line:
values[2]=(line.split('(base 16)')[1].strip())
print (A)
请注意,我将您的文件打开更改为使用 with
context manager,一旦您的代码存在 with
块,它将自动为您 close()
文件。建议手动 open
编辑文件,因为之后您可能会忘记 close()
它。
问题
考虑您代码的 "shape":
f = open('a file')
for values in [ 'some list' ]:
for line in f.readlines():
您的两个循环正在执行此操作:
Start with first value in list
Read all lines remaining in file object f
Move to next value in list
Read all lines remaining in file object f
除了你第一次告诉它 "read all lines remaining" 它会这样做。
所以,除非你有办法将更多行放入 f(这可能发生在像 stdin 这样的异步文件中!)你将 "good" 遍历文件,然后每次后续遍历文件对象将指向文件的末尾,所以你什么也得不到。
一个解决方案
当您处理一个文件时,您希望只处理一次。与其他操作相比,文件 I/O 的开销很大。所以你可以选择 (a) 将整个文件读入内存,然后做任何你想做的事,因为它不再是一个文件;或 (b) 只扫描一次。
如果您选择只扫描一次,简单的解决方案就是反转两个 for 循环。而不是这样做:
for item in list:
for line in file:
改为这样做:
for line in file:
for item in list:
很快!您现在只读取文件一次。
其他注意事项
如果我查看您的代码和示例,您似乎正在尝试对特定键进行 完全匹配 。您 trim 在您的列表中找到 MAC 地址,以根据制造商 ID 核对它们。
这向我表明,您拥有的 列表值(来源 MAC 地址)可能 多得多 。因此,也许您应该考虑将图块的内容读入内存,而不是一次处理一行。
将文件存入内存后,考虑构建一个合适的字典。您有一个键(MAC 前缀)和一个值(制造商)。所以构建类似:
for line in f:
mac = line.split('(base 16)')[0].strip()
mfg = line.split('(base 16)')[1].strip()
mac_to_mfg[mac] = mfg
然后您可以遍历源地址并使用字典的 O(1) 查找对您有利:
for src in A:
prefix = src[1][:8].replace(':', '')
if prefix in mac_to_mfg:
# etc...