我需要将一个大的 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文件加载。我试图避免保存本地副本。
逐行处理文件并创建类似对象的文件的最佳方法是什么,我可以将其作为标准输入发送到 python 中的另一个命令?
最佳答案
我最近做了这个,我可以告诉你有一些丑陋的部分,但这绝对是可能的。我无法在此处逐字粘贴代码,因为它是公司内部的。
基本思路是这样的:
通过像这样生成它来启动使用来自
stdin
的数据的程序:command = subprocess.Popen(command_list, stdin=subprocess.PIPE)
。为每个管道(例如
command.stdin
)启动一个threading.Thread
写入或读取它。如果您有多个管道,则需要多个线程。在主线程中用
command.wait()
等待程序退出。停止(加入)所有线程,这样程序就不会阻塞。 您必须确保线程通过从它们的
target
函数return
自行退出。
简单示例(未经测试!):
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()
关于python - 逐行处理内存中的文件并像python中的对象一样生成文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42898837/