SqlAlchemy эквивалент строки подключения pyodbc с использованием FreeTDS - PullRequest
25 голосов
/ 20 декабря 2010

работают следующие работы:

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

Следующие ошибки:

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

Сообщение об ошибке выше:

DBAPIError: (Ошибка) ('08001', '[08001] [unixODBC] [FreeTDS] [SQL Server] Невозможно подключиться к источнику данных (0) (SQLDriverConnectW)') Нет Нет

Может кто-нибудь указать мне правильное направление? Есть ли способ, которым я могу просто сказать sqlalchemy передать определенную строку подключения через pyodbc?

Обратите внимание: Я хочу оставить этот DSN-менее.

Ответы [ 5 ]

38 голосов
/ 13 сентября 2011

Пример @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))

Это должноприменимо и к Sybase.

ПРИМЕЧАНИЕ. В python 3 модуль urllib был разбит на части и переименован.Таким образом, эта строка в python 2.7:

quoted = urllib.quote_plus

должна быть изменена на эту строку в python3:

quoted = urllib.parse.quote_plus
21 голосов
/ 20 декабря 2010

Мне все еще интересно, как сделать это в одной строке в выражении 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)

ОБНОВЛЕНИЕ : устраняет озабоченность, высказанную мною в моем собственном комментарии о невозможности передачи аргументов в строку подключения.Ниже приведено общее решение, если вам нужно динамически подключаться к различным базам данных во время выполнения.Я передаю только имя базы данных в качестве параметра, но при необходимости можно легко использовать дополнительные параметры:

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
           /76937/chto-takoe-vyzyvaemyi#76943"""
        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))
5 голосов
/ 27 февраля 2011

Это работает:

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

В этом формате 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()
4 голосов
/ 19 октября 2013

Внутренне «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()

становится:

sqlalchemy.create_engine("mssql://myuser:mypwd@my.db.server/mydb?driver=FreeTDS&port=1433& odbc_options='TDS_Version=8.0'").connect()
0 голосов
/ 22 декабря 2010

Чтобы передать различные параметры в вашу функцию соединения, звучит так, как будто строка формата может делать то, что вы хотите:

def connect(server, dbname, user, pass):
  pyodbc.connect('DRIVER={FreeTDS};Server=%s;Database=%s;UID=%s;PWD=%s;TDS_Version=8.0;Port=1433;' % (server, dbname, user, pass))

И затем вы бы назвали его следующим образом:

connect('myserver', 'mydatabase', 'myuser', 'mypass')

Больше информации о строках формата здесь: http://docs.python.org/library/string.html#formatstrings

...