Pythonic способ отправки содержимого файла в канал и подсчета # строк за один шаг - PullRequest
4 голосов
/ 15 декабря 2011

учитывая файл myfile.gz размером> 4 Гб, мне нужно поместить его в канал для потребления быстрой загрузкой Teradata. Мне также нужно посчитать количество строк в файле. В идеале я хочу сделать только один проход через файл. Я использую awk для вывода всей строки ($ 0) в stdout и, используя предложение END в awk, записываю количество строк (переменную NR в awk) в другой файловый дескриптор (outfile).

Мне удалось сделать это с помощью awk, но я хотел бы знать, существует ли более питонический способ.

#!/usr/bin/env python
from subprocess import Popen, PIPE
from os import path

the_file = "/path/to/file/myfile.gz"

outfile = "/tmp/%s.count" % path.basename(the_file)
cmd = ["-c",'zcat %s | awk \'{print $0} END {print NR > "%s"} \' ' % (the_file, outfile)]
zcat_proc = Popen(cmd, stdout = PIPE, shell=True)

Канал позже используется при вызове быстрой загрузки teradata, которая читает из

"/dev/fd/" + str(zcat_proc.stdout.fileno())

Это работает, но я хотел бы знать, возможно ли пропустить awk и лучше использовать python. Я также открыт для других методов. У меня есть несколько больших файлов, которые мне нужно обработать таким образом.

Ответы [ 4 ]

7 голосов
/ 15 декабря 2011

Нет необходимости ни в zcat, ни в Awk. Подсчет строк в сжатом файле можно выполнить с помощью

import gzip

nlines = sum(1 for ln in gzip.open("/path/to/file/myfile.gz"))

Если вы хотите сделать что-то еще со строками, например, передать их другому процессу, выполните

nlines = 0
for ln in gzip.open("/path/to/file/myfile.gz"):
    nlines += 1
    # pass the line to the other process
3 голосов
/ 15 декабря 2011

Подсчет строк и распаковка gzip сжатых файлов могут быть легко выполнены с помощью Python и его стандартной библиотеки. Вы можете сделать все за один проход:

import gzip, subprocess, os
fifo_path = "path/to/fastload-fifo"
os.mkfifo(fifo_path)
fastload_fifo = open(fifo_path)
fastload = subprocess.Popen(["fastload", "--read-from", fifo_path],
                            stdin=subprocess.PIPE)
with gzip.open("/path/to/file/myfile.gz") as f:
    for i, line in enumerate(f):
         fastload_fifo.write(line)
    print "Number of lines", i + 1
os.unlink(fifo_path)

Я не знаю, как вызвать Fastload - заменить правильные параметры в вызове.

1 голос
/ 15 декабря 2011

Это можно сделать одной простой строкой bash:

zcat myfile.gz | tee >(wc -l >&2) | fastload

Это напечатает счетчик строк на stderr. Если вы хотите его где-то еще, вы можете перенаправить вывод wc так, как вам нравится.

0 голосов
/ 10 марта 2015

На самом деле, вообще не должно быть возможности передавать данные в Fastload, поэтому было бы здорово, если бы кто-нибудь опубликовал здесь точный пример, если бы мог.

Из документации Teradata по конфигурации Fastload http://www.info.teradata.com/htmlpubs/DB_TTU_14_00/index.html#page/Load_and_Unload_Utilities/B035_2411_071A/2411Ch03.026.028.html#ww1938556

FILE = имя файла Ключевая фраза, указывающая имя источника данных, который содержит входные данные.fileid должен ссылаться на обычный файл. В частности, трубы не поддерживаются .

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