4

鉴于 > 4gb 文件 myfile.gz,我需要将其 zcat 到管道中以供 Teradata 的快速加载使用。我还需要计算文件中的行数。理想情况下,我只想对文件进行一次传递。我使用 awk 将整行($0)输出到标准输出,并通过使用 awk 的 END 子句,将行数(awk 的 NR 变量)写入另一个文件描述符(outfile)。

我已经设法使用 awk 做到了这一点,但我想知道是否存在更 Pythonic 的方式。

#!/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 的 fastload 消耗,该快速加载从

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

这可行,但我想知道是否可以跳过 awk 并更好地利用 python。我也对其他方法持开放态度。我有多个需要以这种方式处理的大文件。

4

4 回答 4

7

不需要 ofzcat或 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
于 2011-12-15T15:04:24.073 回答
3

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 - 在调用中替换正确的参数。

于 2011-12-15T15:04:56.787 回答
1

这可以在一行简单的 bash 中完成:

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

这将在 stderr 上打印行数。如果您想要它在其他地方,您可以根据需要重定向 wc 输出。

于 2011-12-15T19:20:57.433 回答
0

实际上,根本不可能将数据通过管道传输到 Fastload,所以如果有人可以在这里发布一个确切的示例,那就太好了。

来自关于 Fastload 配置的 Teradata 文档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=filename 关键字短语,指定包含输入数据的数据源的名称。fileid 必须引用常规文件。具体来说,不支持管道

于 2015-03-10T17:51:34.953 回答