sqlalchemy 寻找服务器版本作为字符串,而不是类似字节的对象

sqlalchemy looking for server version as string, instead of bytes-like object

我不知道是什么突然导致了这个(我最近重新安装了 Anaconda 和我所有的 python 库,但我回到了和以前一样的版本),但是当 sqlalchemy 尝试连接到 SQL 服务器,它会失败,因为它会查找服务器版本并尝试对其进行 运行 字符串操作。

以下在我重新安装软件包之前没有问题。我会这样连接:

sqlalchemy_conn_string = 'mssql+pyodbc://myDSN'
sqlalchemy.create_engine(sqlalchemy_conn_string, module=pypyodbc)

然后它一直到一个名为 pyodbc.py 的文件并在此函数处失败:

def _get_server_version_info(self, connection):
  try:
    raw = connection.scalar("SELECT SERVERPROPERTY('ProductVersion')")
  except exc.DBAPIError:
    #...
  else:
    version= []
    r = re.compile(r'[.\-]')
    for n in r.split(raw):  # culprit here
      try:
        version.append(int(n))
      except ValueError:
        version.append(n)
    return tuple(version)

Out[1]: TypeError: cannot use a string pattern on a bytes-like object

那是因为在这一步,raw不是一个可以拆分的字符串:

# from PyCharm's debugger window
raw = {bytes}b'13.0.5026.0'

此时,我不知道是否应该为 sqlalchemy and/or pypyodbc 提交错误报告,或者我是否可以自己解决这个问题。但我想要一个不涉及在我自己的机器上编辑 sqlalchemy 代码的解决方案(比如专门处理类似字节的对象),因为我们还有其他团队成员也将下载 vanilla sqlalchemy 和 pypyodbc 并且不会'没有信心编辑那个源代码。

我已确认 Python 3.6.4.

下的 pypyodbc 行为
print(pypyodbc.version)  # 1.3.5
sql = """\
SELECT SERVERPROPERTY('ProductVersion')
"""
crsr.execute(sql)
x = crsr.fetchone()[0]
print(repr(x))  # b'12.0.5207.0'

请注意,SQLAlchemy 的 mssql+pyodbc 方言是为 pyodbc 编码的,而不是 pypyodbc,并且不能保证两者 100% 兼容。

显而易见的解决方案是改用 pyodbc。

更新:

检查您的 SQLAlchemy 版本。我刚刚查看了 mssql+pyodbc dialect 的当前源代码,它

def _get_server_version_info(self, connection):
    try:
        # "Version of the instance of SQL Server, in the form
        # of 'major.minor.build.revision'"
        raw = connection.scalar(
            "SELECT CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR)")

应该可以避免这个问题,即使在使用 pypyodbc 时也是如此。

如果您使用的是 SQLAlchemy 的最新生产版本(当前版本为 1.2.15),那么使用 1.3.0b1 版本可能会更好。