填充列表时Python内存泄漏如何修复?

2024-10-03 19:32:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一段代码是这样的:

downloadsByExtensionCount = defaultdict(int)
downloadsByExtensionList = []
logFiles = ['file1.log', 'file2.log', 'file3.log', 'file4.log']


for logFile in logFiles:
    log = open(logFile, 'r', encoding='utf-8')
    logLines = log.readlines()

    for logLine in logLines:
        date, time, c_ip, cs_method, s_port, cs_uri_stem, cs_user_agent = logLine.split(" ")

        downloadsByExtensionCount[cs_uri_stem] += 1
        downloadsByExtensionList.append([date, time, c_ip, cs_method, s_port, cs_uri_stem, cs_user_agent])

这四个文件的大小都在150MB左右,每一个文件中有大约60000-80000行。在

我开始只使用这些文件中的一个来编写脚本,因为这样可以更快地测试功能,但是现在我有了所有的逻辑和功能,我当然尝试同时在所有四个日志文件上运行它。当脚本开始从第四个文件获取数据时,我得到的是:

^{pr2}$

所以-我看了一下这个东西消耗了多少内存,这是我发现的:

脚本读取前三个文件,并达到1800-1950MB左右,然后开始读取最后一个文件,增加50-100MB,然后我得到错误。 我试着在脚本中运行,最后一行(append)被注释掉,然后它的总容量达到了500MB左右。在

那么,我做错什么了?这四个文件的总和大约为600MB,而脚本使用大约1500个文件填充列表,其中四个文件中只有三个

我真不明白为什么。。我该如何改进?谢谢您。在


Tags: 文件in脚本logfordateurics
3条回答

您可以使用sqlite3内置模块进行数据操作。您还可以提供特殊名称“:memory:”insted“c:/temp/example”在RAM中创建数据库。如果不存储在RAM中,则限制硬盘的可用空间。在

import sqlite3
from collections import defaultdict

downloadsByExtensionCount = defaultdict(int)
# downloadsByExtensionList = []
logFiles = ['file1.log', 'file2.log', 'file3.log', 'file4.log']


conn = sqlite3.connect('c:/temp/example')
c = conn.cursor()
# Create table
c.execute('create table if not exists logs(date, time, c_ip, cs_method, s_port, cs_uri_stem, cs_user_agent)')

for logFile in logFiles:
    try:
        log = open(logFile, 'rb')#, encoding='utf-8')
    except IOError, e:
        continue

    logLines = log.readlines()

    for logLine in logLines:
        date, time, c_ip, cs_method, s_port, cs_uri_stem, cs_user_agent = logLine.split(" ")

        downloadsByExtensionCount[cs_uri_stem] += 1
        c.execute(
            'insert into logs(date, time, c_ip, cs_method, s_port, cs_uri_stem, cs_user_agent) values(?,?,?,?,?,?,?)', 
            (date, time, c_ip, cs_method, s_port, cs_uri_stem, cs_user_agent)
            )

conn.commit()
conn.close()

log.readlines()将文件内容读入行列表中。可以直接遍历该文件以避免出现额外的列表。在

downloadsByExtensionCount = defaultdict(int)
downloadsByExtensionList = []
logFiles = ['file1.log', 'file2.log', 'file3.log', 'file4.log']


for logFile in logFiles:
    # closes the file after the block
    with open(logFile, 'r', encoding='utf-8') as log:
        # just iterate over the file
        for logLine in log:
            date, time, c_ip, cs_method, s_port, cs_uri_stem, cs_user_agent = logLine.split(" ")
            downloadsByExtensionCount[cs_uri_stem] += 1
            # tuples are enough to store the data
            downloadsByExtensionList.append((date, time, c_ip, cs_method, s_port, cs_uri_stem, cs_user_agent))

直接迭代文件内容:

for logFile in logFiles:

    log = open(logFile, 'r', encoding='utf-8')
    for logLine in log:
        ...
    log.close()

使用tuple代替list

^{pr2}$

相关问题 更多 >