
本文讲解如何安全、可靠地从 python 脚本中调用 psql 命令创建数据库,重点解决因参数传递方式错误导致的“文件未找到”异常([errno 2] no such file or directory)。
本文讲解如何安全、可靠地从 python 脚本中调用 psql 命令创建数据库,重点解决因参数传递方式错误导致的“文件未找到”异常([errno 2] no such file or directory)。
在 Python 中通过 subprocess.Popen 调用外部命令(如 psql)时,绝不能将整个命令行拼接为单个字符串再 .encode() 后传入——这会导致系统试图查找一个名为 "psql -d ..." 的可执行文件(含空格),而非真正执行 psql 程序。你遇到的错误正是因此产生。
✅ 正确做法是:以字符串列表(sequence)形式传入 Popen 的第一个参数,让 subprocess 自动按 POSIX 规则解析参数,避免 shell 注入与路径解析错误:
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
from subprocess import Popen, PIPE
try:
cmd = [
'psql',
'-d', settings.DB_NAME,
'-U', settings.DB_USER,
'-h', settings.DB_HOST,
'-W', # 启用密码提示(实际运行时由 stdin 提供)
'-c', f'CREATE DATABASE {name} OWNER {user};'
]
proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, text=True)
stdout, stderr = proc.communicate(input=settings.DB_PASSWORD + '\n')
if proc.returncode != 0:
raise RuntimeError(f"psql failed: {stderr.strip()}")
print("Database created successfully.")
except Exception as ex:
print(f"Error: {ex}")
⚠️ 关键注意事项:
- 不要使用 shell=True:虽可支持字符串命令,但极大增加 SQL 注入与系统命令注入风险(尤其当 name 或 user 来自用户输入时);
- 密码处理需谨慎:-W 会等待 stdin 输入密码;确保 settings.DB_PASSWORD 无换行符,并在 communicate() 中显式追加 '\n';
-
推荐替代方案:生产环境更建议使用 psycopg2(纯 Python PostgreSQL 驱动)直接连接 postgres 数据库执行 CREATE DATABASE,避免依赖外部二进制和密码明文传输:
import psycopg2 conn = psycopg2.connect(dbname='postgres', user=settings.DB_USER, host=settings.DB_HOST, password=settings.DB_PASSWORD) conn.autocommit = True # CREATE DATABASE requires autocommit with conn.cursor() as cur: cur.execute(f'CREATE DATABASE {name} OWNER {user}')
综上,将命令拆分为参数列表是调用 psql 的安全基石;而长期来看,使用 psycopg2 或 asyncpg 等原生驱动,能提供更强的可控性、错误处理能力与安全性。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










