SqlAlchemy相当于使用FreeTDS的pyodbc连接字符串

mwo*_*e02 26 python sql-server sqlalchemy pyodbc freetds

以下作品:

import pyodbc
pyodbc.connect('DRIVER={FreeTDS};Server=my.db.server;Database=mydb;UID=myuser;PWD=mypwd;TDS_Version=8.0;Port=1433;')
Run Code Online (Sandbox Code Playgroud)

以下失败:

import sqlalchemy
sqlalchemy.create_engine("mssql://myuser:mypwd@my.db.server:1433/mydb?driver=FreeTDS& odbc_options='TDS_Version=8.0'").connect()
Run Code Online (Sandbox Code Playgroud)

上面的错误消息是:

DBAPIError :(错误)('08001','[08001] [unixODBC] [FreeTDS] [SQL Server]无法连接到数据源(0)(SQLDriverConnectW)')无无

有人可以指点我正确的方向吗?有没有办法告诉sqlalchemy将特定的连接字符串传递给pyodbc?

请注意:我希望保持此DSN-less.

jma*_*son 39

@Singletoned的例子不适用于SQLAlchemy 0.7.2.从SQLAlchemy文档连接到SQL Server:

If you require a connection string that is outside the options presented above, use the odbc_connect keyword to pass in a urlencoded connection string. What gets passed in will be urldecoded and passed directly.

为了使它工作,我使用:

import urllib
quoted = urllib.quote_plus('DRIVER={FreeTDS};Server=my.db.server;Database=mydb;UID=myuser;PWD=mypwd;TDS_Version=8.0;Port=1433;')
sqlalchemy.create_engine('mssql+pyodbc:///?odbc_connect={}'.format(quoted))
Run Code Online (Sandbox Code Playgroud)

这也适用于Sybase.

注意:在python 3中,urllib模块已拆分为多个部分并重命名.因此,这行在python 2.7中:

quoted = urllib.quote_plus
Run Code Online (Sandbox Code Playgroud)

必须在python3中更改为此行:

quoted = urllib.parse.quote_plus
Run Code Online (Sandbox Code Playgroud)


mwo*_*e02 22

我仍然对在sqlalchemy create_engine语句中的一行中执行此操作感兴趣,但我在此处找到了以下解决方法:

import pyodbc, sqlalchemy

def connect():
    pyodbc.connect('DRIVER={FreeTDS};Server=my.db.server;Database=mydb;UID=myuser;PWD=mypwd;TDS_Version=8.0;Port=1433;')

sqlalchemy.create_engine('mssql://', creator=connect)
Run Code Online (Sandbox Code Playgroud)

更新:解决我在自己的评论中提出的关于无法将参数传递给连接字符串的问题.如果需要在运行时动态连接到不同的数据库,以下是一般解决方案.我只将数据库名称作为参数传递,但可以根据需要轻松使用其他参数:

import pyodbc
import os

class Creator:
    def __init__(self, db_name='MyDB'):
        """Initialization procedure to receive the database name"""
        self.db_name = db_name

    def __call__(self):
        """Defines a custom creator to be passed to sqlalchemy.create_engine
           http://stackoverflow.com/questions/111234/what-is-a-callable-in-python#111255"""
        if os.name == 'posix':
            return pyodbc.connect('DRIVER={FreeTDS};'
                                  'Server=my.db.server;'
                                  'Database=%s;'
                                  'UID=myuser;'
                                  'PWD=mypassword;'
                                  'TDS_Version=8.0;'
                                  'Port=1433;' % self.db_name)
        elif os.name == 'nt':
            # use development environment
            return pyodbc.connect('DRIVER={SQL Server};'
                                  'Server=127.0.0.1;'
                                  'Database=%s_Dev;'
                                  'UID=user;'
                                  'PWD=;'
                                  'Trusted_Connection=Yes;'
                                  'Port=1433;' % self.db_name)

def en(db_name):
    """Returns a sql_alchemy engine"""
    return sqlalchemy.create_engine('mssql://', creator=Creator(db_name))
Run Code Online (Sandbox Code Playgroud)


Sin*_*ned 5

这有效:

import sqlalchemy
sqlalchemy.create_engine("DRIVER={FreeTDS};Server=my.db.server;Database=mydb;UID=myuser;PWD=mypwd;TDS_Version=8.0;Port=1433;").connect()
Run Code Online (Sandbox Code Playgroud)

在该格式中,SQLAlchemy只是忽略连接字符串并将其直接传递给pyodbc.

更新:

对不起,我忘记了uri必须是url编码的,因此,以下工作:

import sqlalchemy
sqlalchemy.create_engine("DRIVER%3D%7BFreeTDS%7D%3BServer%3Dmy.db.server%3BDatabase%3Dmydb%3BUID%3Dmyuser%3BPWD%3Dmypwd%3BTDS_Version%3D8.0%3BPort%3D1433%3B").connect()
Run Code Online (Sandbox Code Playgroud)

  • 你是对的.看来,在过去1251天的某个时刻,格式发生了变化. (6认同)

gra*_*ier 5

在内部,“my.db.server:1433”作为连接字符串的一部分传递,例如SERVER=my.db.server:1433;.

不幸的是,unixODBC/FreeTDS 不接受 SERVER 位中的端口。相反,它想要SERVER=my.db.server;PORT=1433;

要对连接字符串使用 sqlalchemy 语法,必须指定端口作为参数。

sqlalchemy.create_engine("mssql://myuser:mypwd@my.db.server:1433/mydb?driver=FreeTDS& odbc_options='TDS_Version=8.0'").connect()
Run Code Online (Sandbox Code Playgroud)

变成:

sqlalchemy.create_engine("mssql://myuser:mypwd@my.db.server/mydb?driver=FreeTDS&port=1433& odbc_options='TDS_Version=8.0'").connect()
Run Code Online (Sandbox Code Playgroud)