PostgreSQL COPY导入CSV报UndefinedFile,可读取文件却无法导入
问题根源
PostgreSQL的COPY是服务器端命令,它会让PostgreSQL服务进程去读取指定路径的文件——这个文件必须存在于服务器的文件系统中,或者服务器能直接访问的共享路径里。你用pandas能正常读取CSV,是因为文件在你运行Python脚本的本地机器(客户端)上,但PostgreSQL服务器根本找不到这个本地路径,所以触发了UndefinedFile错误。
解决方案
以下是三种可行的解决方式,按需选择:
方案1:用客户端版COPY(等价psql的\copy)
使用psycopg2的copy_from方法,这是客户端层面的操作,会读取本地文件并将数据发送给服务器,无需服务器访问本地文件:
import glob import psycopg2 conn = psycopg2.connect("你的数据库连接字符串") cur = conn.cursor() file_list = glob.glob("test/*") for file in file_list: file_name = file.split("\\")[1].replace(".csv", "") # 打开本地文件,跳过表头后导入 with open(file, 'r', encoding='utf-8') as f: next(f) # 跳过CSV表头行 cur.copy_from(f, file_name, sep=',') conn.commit() cur.close() conn.close()
如果CSV包含特殊格式(比如带引号的字符串、空值),可以额外指定quotechar、null等参数适配。
方案2:将文件放到服务器可访问路径
把test目录下的CSV文件上传到PostgreSQL服务器的某个目录(比如/tmp/test/),然后修改COPY命令的路径为服务器上的绝对路径。这种方式需要你有服务器的文件操作权限,适合固定批量导入的场景。
方案3:用pandas的to_sql直接导入
既然已经通过pandas读取了DataFrame,直接用to_sql方法将数据写入数据库,无需处理文件路径问题:
import glob import pandas as pd from sqlalchemy import create_engine engine = create_engine("postgresql://用户名:密码@主机:端口/数据库名") file_list = glob.glob("test/*") for file in file_list: df = pd.read_csv(file) file_name = file.split("\\")[1].replace(".csv", "") df.to_sql(file_name, engine, if_exists='append', index=False)
这种方式更简洁,适合数据量不大的场景,底层会自动处理数据插入逻辑。
内容的提问来源于stack exchange,提问作者Bartosz
相关产品推荐
相关产品推荐

