在内存中逐行处理文件并在python中生成类似对象的文件

时间:2017-03-20 08:28:46

标签: python postgresql file sed copy

我需要将大型CSV文件导入postgresql。该文件使用两个分隔符“,”(逗号)和“_”(下划线)。

postgres copy命令无法使用两个分隔符,因此我在将其加载到数据库之前以bash处理该文件:

cat large_file.csv \ 
| sed -e 's/_/,/' \ 
| psql -d db -c "COPY large_table FROM STDIN DELIMITER ',' CSV header"

```

我正在尝试在python中重现这个命令,我很难找到sed的python等价物。

使用psycopg我可以使用python:

从STDIN复制
with unzip('large_zip.zip', 'large_file.csv') as file:
    cr.copy_expert('''
        COPY large_table
        FROM STDIN
        DELIMITER ',' CSV HEADER
   ''', file)

文件非常大,直接从zip文件加载。我试图避免保存本地副本。

逐行处理文件并创建像object这样的文件的最佳方法是什么?我可以作为标准输入发送到python中的另一个命令?

1 个答案:

答案 0 :(得分:0)

我最近这样做了,我可以告诉你有一些丑陋的部分,但绝对可能。我不能逐字地粘贴代码,因为它是公司内部的。

基本理念是:

  1. 启动程序,该程序使用stdin生成数据,方法是这样生成:

    command = subprocess.Popen(command_list, stdin=subprocess.PIPE)

  2. 为每个管道(例如command.stdin)启动一个threading.Thread,它写入或读取它。如果您有多个管道,则需要多个线程。
  3. 等待主线程中command.wait()退出程序。
  4. 停止(加入)所有线程,以便程序不会阻止。 必须确保线程通过return函数target自行退出。
  5. 简单示例(未测试!):

    import shutil
    import subprocess
    import sys
    import threading
    
    
    lots_of_data = StringIO.StringIO()
    
    import_to_db = subprocess.Popen(["import_to_db"], stdin=subprocess.PIPE)
    
    # Make sure your input stream is at pos 0
    lots_of_data.seek(0)
    
    writer = threading.Thread(target=shutil.copyfileobj,
                              args=(lots_of_data, import_to_db.stdin))
    
    writer.start()
    
    return_code = import_to_db.wait()
    if return_code:
        print "Error"
        sys.exit(1)
    
    writer.join()