Python извлекает ключевые слова из нескольких файлов .gz - PullRequest
0 голосов
/ 04 ноября 2019

Вопрос: Как искать ключевые слова из нескольких файлов в Python (включая сжатый файл gz и несжатый файл) У меня есть несколько архивных журналов в папке, последний файл - «сообщения», а старые журналы будут автоматически сжаты как. Файл gz.

  • -rw ------- 1 корневой корень 21262610 4 ноября 11:20 сообщений

  • -rw------- 1 корневой корень 3047453 2 ноября 15:49 messages-20191102-1572680982.gz

  • -rw ------- 1 корневой корень 3018032 3 ноября 04:43 messages-20191103-1572727394.gz

  • -rw ------- 1 root root 3026617 3 ноября 17:32 messages-20191103-1572773536.gz

  • -rw ------- 1 root root 3044692 4 ноября, 06:17 messages-20191104-1572819469.gz

Я написал функцию:

  1. сохранить все имена файлов в списке. (Успех)
  2. открыть каждый файл в списке, если это файл gz, используйте gzip.open ().
  3. поиск по ключевым словам

но я думаю, что этот способ не очень умен, потому что на самом деле журнал сообщений очень большой, и он разделен на несколько файлов gz. И у меня много ключевых словхранится в файле ключевых слов.

Итак, есть ли лучшее решение объединить все файлы в поток ввода-вывода и затем извлечь ключевые слова из потока.

def open_all_message_files(path):

    files_list=[]
    for root, dirs, files in os.walk(path):
        for file in files:
            if file.startswith("messages"):
                files_list.append(os.path.join(root,file))

    for x in files_list:
            if x.endswith('gz'):
                with gzip.open(x,"r") as f:
                    for line in f:
                        if b'keywords_1' in line:
                          print(line)
                        if b'keywords_2' in line:
                          print(line)
            else:
                with open(x,"r") as f:
                    for line in f:
                        if 'keywords_1' in line:
                            print(line)
                        if 'keywords_2' in line:
                            print(line)

1 Ответ

0 голосов
/ 04 ноября 2019

Это мой первый ответ в stackoverflow, поэтому, пожалуйста, потерпите меня. У меня была очень похожая проблема, когда мне нужно было проанализировать несколько журналов, некоторые из которых были огромными, чтобы полностью поместиться в память. Решением этой проблемы является создание конвейера обработки данных, аналогичного конвейеру Unix / Linux. Идея состоит в том, чтобы разбить каждую задачу на отдельные функции и использовать генераторы для достижения более эффективного использования памяти.

import os
import gzip
import re
import fnmatch

def find_files(pattern, path):
    """
    Here you can find all the filenames that match a specific pattern
    using shell wildcard pattern that way you avoid hardcoding
    the file pattern i.e 'messages'
    """
    for root, dirs, files in os.walk(path):
        for name in fnmatch.filter(files, pattern):
            yield os.path.join(root, name)

def file_opener(filenames):
    """
    Open a sequence of filenames one at a time
    and make sure to close the file once we are done 
    scanning its content.
    """
    for filename in filenames:
        if filename.endswith('.gz'):
            f = gzip.open(filename, 'rt')
        else:
            f = open(filename, 'rt')
        yield f
        f.close()

def chain_generators(iterators):
    """
    Chain a sequence of iterators together
    """
    for it in iterators:
        # Look up yield from if you're unsure what it does
        yield from it

def grep(pattern, lines):
    """
    Look for a pattern in a line
    """
    pat = re.compile(pattern)
    for line in lines:
        if pat.search(line):
            yield line

# A simple way to use these functions together

logs = find_files('messages*', 'One/two/three')
files = file_opener(logs)
lines = chain_generators(files)
each_line = grep('keywords_1', lines)
for match in each_line:
    print(match)

Дайте мне знать, если у вас есть какие-либо вопросы относительно моего ответа

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...