如何优化(也是 RAM 明智的)将单词从 PDF 保存到 Python 对象然后保存到数据库中的代码?

How to optimize (also RAM wise) code that is saving words from PDF to Python object and later into database?

我正在寻找将文本从 PDF 文件保存到我的数据库中的最有效方法。目前我正在使用 pdfplumber,标准代码如下所示:

my_string = ''

with pdfplumber.open(text_file_path) as pdf:
    for page in pdf.pages:
        if page.extract_text():
            my_string += str(page.extract_text().replace('\n', ' ').split(' '))

但目前的代码是文学性的杀死我的机器(600 页的 PDF 需要大约 3 到 6 GB 的内存),我的目标是在手机上实际托管它。

我做了一些测试,阅读PDF似乎没有问题,但是保存或存储这些文字是有问题的。我尝试创建字典,其中每个页面字符串都是一个 key/value,但并没有好多少。

也许我应该尝试将每个页面生成到 txt 文件中,然后从该 txt 文件中读取字符串?

如有任何提示,我将不胜感激,谢谢!

编辑:

    with pdfplumber.open(text_file_path) as pdf:
        for page in pdf.pages:
            connection = sqlite3.connect('my_db.db')
            cursor = connection.cursor()
            cursor.execute("INSERT INTO temp_text VALUES (?, ?)",
                           (text_file_path, str(page.extract_text()).replace('\n', ' ')))
            connection.commit()
            connection.close()

我更改了代码,它稍微好一点,(现在它占用大约 2.9 GB 的 RAM)但它仍然很多。我还能做些什么吗?

问题是您要长期存储数据,这意味着随着您逐渐处理越来越多的数据,您仍然在内存中引用它们。这就是数据库旨在防止的:所有高效的数据存储和检索,而无需将其全部存储在 RAM 中。下面是一个使用 PyMongo 的简单示例(对于 iOS 应用程序,您可能会想要使用 SQLite):

import pdfplumbder
import poymongo
import os


def process_file(path, collection):
    '''Process a single file, from a path.'''

    basename = os.path.splitext(os.path.basename(path))[0]
    with pdfplumber.open(path) as pdf:
        for index, page in enumerate(pdf.pages):
            # Don't store any long-term references to the data
            text = page.extract_text()
            data = { 'text': text, 'filename': basename, 'page': index }
            collection.insert_one(data)

def main(paths):
    '''Just a dummy entry point, pass args normally here.'''

    client = pymongo.MongoClient('localhost', 27017)
    database = client['myapp']
    collection = database['pdfs']
    # Sort by filename, then by page.
    collection.create_index([('filename', 1), ('page', 1)])
    for path in paths:
        process_file(path, collection)

    # Do what you want here

如您所见,我们创建了到本地客户端的连接,创建或访问我们正在使用的数据库,并创建了一个用于 PDF 存储的集合。然后我们按文件名索引,然后是页码。

然后我们遍历所有路径,并迭代处理它们。我们不会一次存储超过一页的文本,并且每次循环都将数据写入数据库。就性能而言,这可能不是最佳选择(尽管引擎可能会对此进行适当优化),但它会最大限度地减少所需的内存。

避免使用处理数 GB 数据的全局状态:您迫使 Python 在不需要时保留对所有数据的引用。