You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python subprocess传密码执行pg_dump在Ubuntu18+Python3.6环境失效问题

问题原因分析
  • Ubuntu 18默认搭载的PostgreSQL客户端版本过低,老版本pg_dump默认优先从控制终端/dev/tty读取密码,而非标准输入stdin,你通过p.communicate往stdin写入的密码不会被pg_dump识别,自然会弹出终端密码输入提示。Mac、Ubuntu 20环境下的PostgreSQL客户端版本更高,已适配支持从stdin读取密码的逻辑,所以可以正常运行。
  • Python 3.6的subprocess.Popen在shell=True配置下的管道转发逻辑存在差异,你写入stdin的内容实际上是传给了中间启动的shell进程,没有直接递交给pg_dump子进程,老版本的shell管道转发逻辑不完善进一步导致密码传递失败。
  • 你的命令中同时使用了shell级别的输出重定向> {dir}{filename}.dump和Popen(stdout=PIPE)配置,二者存在冲突,Python 3.6及Ubuntu 18自带的bash没有兼容这种冲突场景,进一步打乱了标准输入输出的管道链路。
兼容解决方案

优先使用PostgreSQL官方支持的密码传递方式,完全避免stdin传密码的兼容问题:

  • 方案1:通过PGPASSWORD环境变量传递密码,不需要修改原有命令逻辑,全版本PostgreSQL客户端均支持,示例代码如下:
import os
from subprocess import Popen, STDOUT

# 拷贝当前进程的环境变量,新增PGPASSWORD配置
env = os.environ.copy()
env['PGPASSWORD'] = db_password

command = 'pg_dump -U {user} -h localhost {db_name} > {dir}{filename}.dump'.format(
    user=db_user, db_name=db_name, dir=self._dump_dir, filename=backup_file_name)
# 传入自定义环境变量,不需要再往stdin写密码
p = Popen(command, shell=True, env=env, stderr=STDOUT)
p.wait()
  • 方案2:如果不想用环境变量,也可以把密码写入~/.pgpass配置文件,修改权限为600即可,pg_dump会自动读取该文件中的密码,不需要在代码中传递密码。

内容的提问来源于stack exchange,提问作者Евгений Губаев

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 05:30:04