subprocess.popen 和 psql

4 投票
2 回答
3156 浏览
提问于 2025-04-16 11:56

我有一个Django应用程序,需要调用psql(PostgreSQL的命令行工具)。我是在一个celery线程中这样做的,代码看起来是这样的:

@task()
def insert_sqldump_threaded(username, database, file):
  host = database.server.db_address

  work = subprocess.Popen([settings.PSQL, 
                          "-f%s" % file, 
                          "-d%s" % database.db_name,
                          "-h%s" % host,
                          "-U%s" % settings.DB_ADMIN_USER
                          ], env = {'PGPASSFILE': settings.DB_PASSFILE}
                          )
  work.wait()
  return work.returncode

在我的开发服务器上,PGPASSFILE的内容是这样的:

localhost:5432:*:postgres:postgres

这应该没问题。

但是问题是,当这个函数被调用时,我只收到psql的错误信息:

psql: could not translate host name "localhost" to address: Unknown server error

接下来事情变得有点奇怪,当我不提交“env”变量时,psql似乎能识别主机。至少那时它会要求输入密码。

有没有什么想法可以解决这个问题?

2 个回答

0

当你不提交环境变量时,它会从你正在使用的命令行环境中获取这些变量——可以参考一下os.environ。它可能是依赖这些变量来查找本地服务器的。你需要把这些变量放进字典里。或者直接把os.environ里的所有内容都复制过来。

3

我觉得 PostgreSQL 需要一些其他的环境变量,而这些变量在你使用 env 命令时会被清除。你可以简单地修改 os.environ,或者像下面的代码那样提前做一个副本:

import os
@task()
def insert_sqldump_threaded(username, database, file):
  d = dict(os.environ)
  d['PGPASSFILE'] = settings.DB_PASSFILE
  host = database.server.db_address

  work = subprocess.Popen([settings.PSQL, 
                          "-f%s" % file, 
                          "-d%s" % database.db_name,
                          "-h%s" % host,
                          "-U%s" % settings.DB_ADMIN_USER
                          ], env = d
                          )
  work.wait()
  return work.returncode

撰写回答