繁体   English   中英

如何在Python中处理大量数据

[英]How to deal with large amount of data in Python

我有一个包含大量数据(3 GB)的文本文件。 此文本文件的每一行包含时间,源IP,目标IP和大小。 如您所知,IP地址最后一节中的数字显示端口地址。 我想把这些端口地址带到一个直方图中,我为它做了10 000行数据,但我猜想Python代码不能为大量数据执行。 我简要解释一下我写的代码。 首先,我读取了10 000个数据点,之后我将它们拆分并将所有内容放入名为everything_list的列表中。 只需忽略while循环工作的条件。 后来我将所有端口地址放在一个列表中并绘制了那些的直方图。 现在假设我有数百万条数据线,我首先无法读取它们,更不用说对它们进行分类了。 有人告诉我使用数组,有人告诉我处理数据块,然后再处理另一数据块。 我很困惑所有人说。 有人可以帮我解决这个问题吗?

text_file = open("test.data", "r")
a = text_file.read()
text_file.close()

everything_list = a.split()
source_port_list = []
i=0
while 6+7*i<len(everything_list):

    source_element = everything_list[2+7*i]
    source_port_position = source_element.rfind('.')
    source_port_number = int(source_element[source_port_position + 1:])
    source_port_list.append(source_port_number)

    i=i+1


import matplotlib.pyplot as plt
import pylab


numBins = 20
plt.hist(source_port_list, numBins, color='red', alpha=0.8)
plt.show()

这是行格式:

15:42:42.719063 IP 129.241.138.133.47843 > 129.63.27.12.2674: tcp 1460
15:42:42.719205 IP 129.241.138.133.47843 > 129.63.27.12.2674: tcp 1460
15:42:42.719209 IP 129.63.57.175.45241 > 62.85.5.142.55455: tcp 0
15:42:42.719213 IP 24.34.41.8.1236 > 129.63.1.23.443: tcp 394
15:42:42.719217 IP 59.167.148.152.25918 > 129.63.57.40.36075: tcp 0
15:42:42.719260 IP 129.63.223.16.2823 > 80.67.87.25.80: tcp 682
15:42:42.719264 IP 129.63.184.118.2300 > 64.111.215.46.80: tcp 0
15:42:42.719269 IP 129.63.184.118.2300 > 64.111.215.46.80: tcp 0

我不知道数据是什么样的,但我认为问题是你试图将它全部保存在内存中。 你需要一点一点地做, 逐一阅读这些行并随时建立直方图。

histogram = {}
with open(...) as f:
    for line in f:
        ip = ...
        if ip in histogram:
            histogram[ip] += 1
        else:
            histogram[ip] = 1

您现在可以绘制直方图,但是请使用plt.plot而不是plt.hist因为您已经在histogram字典中有了频率。

您可以使用正则表达式并循环外进行编译。

完全以懒惰模式逐行读取文件。

import re
import matplotlib.pyplot as plt
import pylab

r = re.compile(r'(?<=\.)[0-9]{2,5}(?= \>)')
ports = []

for line in open("test.data", "r"):
    ports.append(re.search(r, line).group(0))

# determines the number of lines you want to take into account
i = (len(ports) - 6) // 7

# keeps only the first i elements
ports = ports[0:i]

numBins = 20
plt.hist(ports, numBins, color='red', alpha=0.8)
plt.show()

此代码考虑到您只需要(n-6) / 7第一项, n是源文件的行数。 如果不太准确,请尝试一些+1/-1 最后,消除不需要的项目使您的循环不会因每次迭代中检查条件而麻烦。

编辑:

您可以结合上面的几个方面来获得更简洁有效的代码:

import re
import matplotlib.pyplot as plt
import pylab

r = re.compile(r'(?<=\.)[0-9]{2,5}(?= \>)')

ports = [ re.search(r, line).group(0) for line in open("test.data", "r") ]
ports = ports[0:(len(ports) - 6) // 7]

numBins = 20
plt.hist(ports, numBins, color='red', alpha=0.8)
plt.show()

编辑:

如果您认为您的端口列表太大而无法放入RAM(我觉得不太可能),我的建议是使用端口字典:

ports = {}
for line in open("test.data", "r"):
    port = re.search(r, line).group(0)
    if not ports.get(port, False):
        ports[port] = 0
    ports[port] += 1

哪个会给你这样的东西:

>>> ports
{
    "8394": 182938,
    "8192": 839288,
    "1283": 9839
}

请注意,在这种情况下,您必须修改对plt.hist的调用。

您可以使用split和defaultdict来提高效率:

from collections import defaultdict

d = defaultdict(int)
with open("a_file.txt") as f:
    for line in f:
         d[line.split()[2].rsplit(".",1)[-1]] += 1 
print(d)

defaultdict(<type 'int'>, {'1236': 1, '2300': 1, '47843': 2, '45241': 1, '25918': 1, '2823': 1})

可能还需要检查一下不同的绘制方式,matplotlib并不是最有效的:

pyqtgraphguiqwtgnuplot.py

听起来你应该逐行迭代并使用正则表达式来查找端口。 尝试这样的事情:

import re

ports = []
with open("path/to/your/text/file.txt", 'r') as infile:
    for line in infile:
        ports.append(re.findall(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\.(\d+)", line))
        # that regex explained:
        # # re.compile(r"""
        # #     \d{1,3}\.       # 1-3 digits followed by a literal .
        # #     \d{1,3}\.       # 1-3 digits followed by a literal .
        # #     \d{1,3}\.       # 1-3 digits followed by a literal .
        # #     \d{1,3}\.       # 1-3 digits followed by a literal .
        # #     (               # BEGIN CAPTURING GROUP
        # #       \d+           #   1 or more digits
        # #     )               # END CAPTURING GROUP""", re.X)

这是假设您的IP /端口已按照注释中的说明进行格式化

IP.IP.IP.IP.PORT

我知道这不是对您的问题的立即答复,但是作为python的新手,有一门很好的Coursera课程涉及该主题。 “为每个人编程(Python)”它是免费的,不会占用你太多的时间。 该课程将于2015年2月2日开始。此外,教科书“信息学的Python:探索信息”也可以免费下载。 http://www.pythonlearn.com/book.php我希望这会有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM