Оболочка stdout PYTHON обрабатывает намного медленнее, чем PYTHON обработка текстовых файлов - PullRequest
0 голосов
/ 01 апреля 2020

Я выполняю задачу разбора / обработки «больших» необработанных данных, сгенерированных из оболочки unix. Эти необработанные данные необходимо проанализировать, чтобы очистить их от некоторых специальных символов.

В конечном итоге я хочу избежать необходимости большого временного файла и делать это на лету.

Способ 1 создает большой временный текстовый файл объемом 8 ГБ (не желательно), но быстро (8 минут выполнения): сначала я генерирую временный необработанный текстовый файл (я помещаю выходные данные оболочки в текстовый файл), а затем анализирую, используя следующий код: Время выполнения 8 минут, размер выходного файла 800 МБ:

f = open(filepath, 'r')
fOut= open(filepathOut,"w+")
for line in f:
    if len(line) > 0:
        if "RNC" in line:
            rncflag = 1
            #quito enter, quito cadena a la izquierda y quito comillas a la derecha
            currline = line.strip('\n').strip('\t').replace(".",",").replace(" ","").lstrip(";")
        else:
            currline = line.strip('\n').strip('\t').replace(".",",").replace(" ","").lstrip(";")

        if rncflag == 1:
            if lineNumOne == 1:
                processedline = currline
                lineNumOne = 0
            else:
                processedline = '\n' + currline
            rncflag = 0
        else:
            processedline = currline

    fOut.write(processedline)
fOut.close()

Способ 2, на лету непосредственно из стандартного вывода (~ 1,5 часа полного выполнения): я бы предпочел это, поскольку мне не нужно генерировать предыдущий необработанный файл для анализа. Я использую библиотеку подпроцесса, чтобы анализировать / обрабатывать оболочку stdout unix непосредственно построчно, пока она генерируется (например, если это где строки в текстовом файле). Проблема в том, что он бесконечно медленнее, чем предыдущий способ. Время выполнения более 1,5 часов, чтобы получить тот же выходной файл (размер 800 МБ):

cmd = subprocess.Popen(isqlCmd, shell=True, stdout=subprocess.PIPE)
for line in cmd.stdout:
    if len(line) > 0:
        if "RNC" in line:
            rncflag = 1
            #quito enter, quito cadena a la izquierda y quito comillas a la derecha
            currline = line.strip('\n').strip('\t').replace(".",",").replace(" ","").lstrip(";")
        else:
            currline = line.strip('\n').strip('\t').replace(".",",").replace(" ","").lstrip(";")

        if rncflag == 1:
            if lineNumOne == 1:
                processedline = currline
                lineNumOne = 0
            else:
                processedline = '\n' + currline
            rncflag = 0
        else:
            processedline = currline

    fOut.write(processedline)

fOut.close()

Я не python эксперт, но я уверен, что есть способ ускорить обработку если unix stdout на лету, вместо того, чтобы предварительно генерировать необработанный файл, чтобы проанализировать его после того, как он был сгенерирован.

Цель программы - очистить / проанализировать выходные данные запроса sybase i sql. Примечание: библиотека sybase не может быть установлена.

Python версия является -> Python 2.6.4 и не может быть изменена

Заранее спасибо, любые улучшения приветствуются.

1 Ответ

1 голос
/ 03 апреля 2020

Без возможности воспроизвести проблему канонический ответ невозможен - но можно предоставить инструменты, необходимые для сужения проблемы.

Если вы переключитесь с использования subprocess.Popen(..., stdout=subprocess.PIPE) на просто чтение из sys.stdin безусловно, это означает, что мы можем использовать один и тот же код в и случае чтения из файла (в этом случае вы захотите запустить ./yourscript <inputfile), и в случай «труба из процесса» (./runIsqlCommand | ./yourscript), поэтому мы можем быть уверены, что мы проводим тестирование «как для сравнения».

Как только это будет сделано, это также даст нам возможность поместить буферизацию в место, чтобы стороны трубопровода не блокировали друг друга без необходимости. Для этого это может выглядеть следующим образом:

./runIsqlCommand | pv | ./yourscript

... где pv - это Pipe Viewer , инструмент, который предоставляет индикатор выполнения (когда известен общий объем контента) ), индикатор пропускной способности и - что крайне важно для наших целей - гораздо больший буфер, чем по умолчанию операционной системы, и место для дальнейшей настройки этого размера (и мониторинга потребления).

Чтобы определить, является ли Python скрипт работает медленнее, чем код SQL, скажите pv, чтобы он отображал потребление буфера с аргументом -T. (Если это показывает ----, то pv использует системный вызов splice() для передачи содержимого между процессами напрямую, без фактического выполнения буферизации; аргумент -C увеличит накладные расходы pv, но убедитесь, что это действительно возможность выполнять буферизацию и отчет о содержимом буфера). Если буфер заполнен на 100% почти все время, то мы знаем, что SQL генерируется быстрее, чем Python может его прочитать; если оно обычно пустое, мы знаем, что Python идет в ногу.

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