【问题标题】:How to set the "chunk size" of read lines from file read with Python subprocess.Popen() or open()?如何从使用 Python subprocess.Popen() 或 open() 读取的文件中设置读取行的“块大小”?
【发布时间】:2016-09-15 11:28:34
【问题描述】:

我有一个相当大的文本文件,我想分块运行。为了使用subprocess 库执行此操作,需要执行以下 shell 命令:

"cat hugefile.log"

用代码:

import subprocess
task = subprocess.Popen("cat hugefile.log", shell=True,  stdout=subprocess.PIPE)
data = task.stdout.read()

使用print(data) 将立即吐出文件的全部内容。如何显示块的数量,然后按块大小访问该文件的内容(例如,块 = 一次三行)。

它必须是这样的:

chunksize = 1000   # break up hugefile.log into 1000 chunks

for chunk in data:
    print(chunk)

与 Python open() 等价的问题当然使用代码

with open('hugefile.log', 'r') as f:
     read_data = f.read()

你会如何read_data 分块?

【问题讨论】:

    标签: python bash shell subprocess chunking


    【解决方案1】:

    使用文件,可以对文件句柄进行迭代(不需要子进程打开cat):

    with open('hugefile.log', 'r') as f:
         for read_line in f:
            print(read_line)
    

    Python 通过读取直到\n 的所有字符来读取一行。要模拟逐行 I/O,只需调用 3 次即可。或读取并计算 3 个 \n 字符,但您必须处理文件结尾等...不是很有用,这样做不会获得任何速度。

    with open('hugefile.log', 'r') as f:
         while True:
            read_3_lines = ""
            try:
               for i in range(3):
                   read_3_lines += next(f)
            # process read_3_lines
            except StopIteration:  # end of file
                # process read_3_lines if nb lines not divisible by 3
                break
    

    使用Popen 你可以做同样的事情,作为奖励添加poll 来监控过程(cat 不需要,但我想你的过程不同,这只是为了问题的目的)

    import subprocess
    task = subprocess.Popen("cat hugefile.log", shell=True,  stdout=subprocess.PIPE)
    while True:
        line = task.stdout.readline()
        if line == '' and task.poll() != None: break
    
    rc = task.wait()   # wait for completion and get return code of the command
    

    支持编码的 Python 3 兼容代码:

        line = task.stdout.readline().decode("latin-1")
        if len(line) == 0 and task.poll() != None: break
    

    现在,如果您想将文件拆分为给定数量的块:

    • 你不能使用Popen,原因很明显:你必须先知道输出的大小
    • 如果您有一个文件作为输入,您可以执行以下操作:

    代码:

    import os,sys
    filename = "hugefile.log"
    filesize = os.path.getsize(filename)
    nb_chunks = 1000
    chunksize = filesize // nb_chunks
    
    with open(filename,"r") as f:
       while True:
          chunk = f.read(chunksize)
          if chunk=="":
              break
          # do something useful with the chunk
          sys.stdout.write(chunk)
    

    【讨论】:

    • 谢谢。我不知道三行的先验知识是什么,但我只想将文件拆分为10**7 块?
    • 你的意思是 10**7 字节的块?你需要Popen吗?你的真实案例是使用cat 还是只是为了问题的简单性?
    • 我的意思是将文件分成 10**7 个部分,而不用担心字节大小。在上面的例子中,nb_chunks 是 1000 字节——如果我们解析每个大小为 750 字节的行,会不会有一些行被截断?我需要 Popen(),是的。猫就是一个简单的例子
    • 如果我们想逐行工作,我们必须知道chunksize 中正确的字节数。
    • rc = task.wait() 是做什么用的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-26
    • 2021-10-22
    • 2016-04-16
    • 1970-01-01
    • 2011-10-29
    • 1970-01-01
    • 2015-07-07
    相关资源
    最近更新 更多