pyodbc + PostgreSQL ODBC:连接字符串有效,DSN 无效

pyodbc + PostgreSQL ODBC: connection string works, DSN doesn't

我正在尝试连接到为 Django 应用构建的 Postgres 数据库。我可以在 windows 中正常连接,但是当我们将其移至 Linux 服务器进行生产时,它停止工作了。我追踪到 pyodbc 不工作。因此,在一个单独的脚本中,我一直在尝试建立一个没有运气的连接。我很确定 Linux 服务器是 运行 Redhat(yum 是安装程序,但我可以仔细检查它是否重要)

以下是我尝试过的一些方法: 安装了 unixODBC-devel

添加了一个 DSN 到用户 sourcename /home/localUsername/.odbc.ini 文件如下:

[DSNName]
Description=Postgres Connection to Database
Driver=/usr/pgsql-10/lib/psqlodbc.so
Server=servername
Database=dbname
PWD=pass
UID=username

运行 odbcinst -q -d returns: [PostgreSQL]

python 我试过的脚本(虽然现在使用解释器)

con = odbc.connect("DSN=DSNName")
con = odbc.connect("Driver={PostgreSQL};Uid=username;Pwd=pass; Server=servername;Port=5432)
con = odbc.connect("Driver={PostgreSQL Unicode(x64)};Uid=username;Pwd=pass; Server=servername;Port=5432)

根据我尝试使用的驱动程序,我会遇到以下三种错误之一: 对于使用 Unicode(x32) 的驱动程序,我得到:

pyodbc.Error ('01000', "[01000] [unixODBC][Driver Manager]can't open lib 'PostgreSQL Unicode(x32)' : file not found ...

我想这意味着没有安装这个驱动程序,这很好。

对于 DSN 方法,我得到:

pyodbc.OperationalError: ('08001', '[08001] FATAL: role:"localUsername" does not exists\n (101) (SQLDriverConnect)')

第二个错误似乎让我认为(可能是错误的)它正在尝试使用我的本地用户名向 Postgres 进行身份验证,而我现在想使用为主机设置的特殊管理员用户名。

对于第三个选项(PostgreSQL):

pyodbc.OperationalError 08001 FATAL: database "dbname" does not exist

我不明白为什么会这样?我的第一个想法是 Linux 想使用不同的端口进行连接。在 windows 本地,我可以使用 5432 端口并且工作正常。所以我不知道如何让它找到数据库,假设其余部分工作正常。

如果您需要更多详细信息,请告诉我,我会尽力添加。

编辑: 在一台服务器上安装 python(和 Django)。 DB 在另一个上。

已尝试 运行 psql -h OSServername -U 'username' 相同:角色 error/DB 未找到错误。我觉得我必须在 OSServername 之后需要一些东西,比如 'OsServername/pgAdminServer' 但这没有用

其中 db 'username' 是通过在 pgAdmin 中右键单击数据库服务器名称之一并选择属性来找到的。 pgAdmin 中的服务器名称是否不同,我是否需要以某种方式使用 pgAdmin 服务器名称作为连接字符串的一部分?

正如评论所建议的那样,从 psql -h 命令开始似乎是一个很好的起点,因为它摆脱了 python 的复杂性。一旦我可以使该命令正常工作,我就可以修复其余部分。当我的 Linux 服务器名称(主机名)是 'LinuxName',pgAdmin 服务器是 'pgAdminServer',实际数据库的名称是 'dbName',pgAdmin 用户名是'username'。 'dbName' 有一个所有者 'owner',它不同于 pgServer 的用户名,也不同于我登录的 Linux 用户名。我还验证了 'pgAdminServer' 显示端口 5432,所以这不应该是问题。

编辑 2: 我让 pyodbc.connect('Driver={PostgreSQL};Server=servNm;Uid=uid;pwd=pwd;Database=db') 开始工作。 现在只需要 DSN 方法的最后一步。您的 dump_dsn 努力在我的 dsn 文件中找到拼写错误(在我的本地主目录中。odbc.ini)。所以这有帮助。仍然没有找到数据库。 文件在:/etc/odbcinst.ini 列出我在我的 DSN 文件中尝试过的所有三个驱动程序:

/usr/pgsql-10/lib/psqlodbc.so
/usr/pgsql-10/lib/psqlodbca.so
/usr/pgsql-10/lib/psqlodbcw.so

这里是我在 home/user/.odbc.ini 中的 .odbc.ini 文件中的信息: 变量:servNm、uid、db 和 pwd 与我的 pyodbc.connect() 字符串中找到的那些完全匹配,现在可以正常工作。

[DSNName]
Description=Postgres Connection to Database
Driver=/usr/pgsql-10/lib/psqlodbc.so
Server=servNm
CommLog=0
Debug=0
Fetch=100
UniqueIndex=1
UseDeclareFetch=0
Database=db
UID=uid
Username=uid
PWD=pwd
ReadOnly=0

删除并重新创建 ~/.odbc.ini 文件似乎已解决问题。这使我们怀疑该文件的前一版本中有一个或多个异常字符导致了奇怪的行为。

这种麻烦的(有时甚至是看不见的!)字符的一个可能来源是从网络上复制文本。如果我们从网络浏览器复制以下内容……

DRIVER=PostgreSQL Unicode

... 并使用默认编码 UTF-8 将其粘贴到我们的文本编辑器中的空白文档中,然后一切看起来都很正常。但是,如果我们保存该文件(作为 UTF-8)并在十六进制编辑器中打开它,我们可以看到 space 不是正常的 space (U+0020) …

…它是一个 NO-BREAK SPACE(a.k.a."NBSP", U+00A0, \xc2\xa0 UTF-8 编码)所以我们得到的机会很大尝试使用该 DSN 时出错,因为 b'PostgreSQL\xc2\xa0Unicode'b'PostgreSQL Unicode' 不同。

我遇到了完全相同的问题。我寻找了几种解决方案,但 none 奏效了。

问题比我想象的更容易解决:

1 - 删除所有关于 postgresodbc 的包:

$ sudo apt-get remove odbc-postgresql

2 - 安装两个库,顺序如下:

$ apt-get install libcppdb-postgresql0 odbc-postgresql

尽情享受吧!

这样做在这里效果很好。