SqlAlchemy équivalent de pyodbc chaîne de connexion à l'aide de FreeTDS

les œuvres suivantes:

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

échoue:

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

le message d'erreur pour CI-DESSUS est:

DBAPIError: (erreur) ('08001', '[08001] [unixODBC] [FreeTDS] [SQL Server]Unable to connect to data source (0) (SQLDriverConnectW)') None None

quelqu'un peut-il m'indiquer la bonne direction? Y a-t-il un moyen que je puisse simplement dire à sqlalchemy passer une chaîne de connexion spécifique à pyodbc?

s'il vous Plaît Note: je veux garder cette DSN.

21
demandé sur mwolfe02 2010-12-20 23:28:22

5 réponses

l'exemple de @Singletoned ne fonctionnerait pas pour moi avec SQLAlchemy 0.7.2. De la Docs SQLAlchemy pour se connecter au serveur SQL :

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.

alors pour que ça marche j'ai utilisé:

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))

cela devrait s'appliquer aussi à Sybase.

NOTE: En python 3, le module urllib a été divisé en parties et renommé. Ainsi, cette ligne en python 2.7:

quoted = urllib.quote_plus

doit être changé pour cette ligne en python3:

quoted = urllib.parse.quote_plus
30
répondu jmagnusson 2017-10-19 15:45:05

je suis toujours intéressé par une façon de le faire dans une ligne dans la déclaration sqlalchemy create_engine , mais j'ai trouvé la solution suivante détaillé ici :

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)

UPDATE : répond à une préoccupation que j'ai soulevée dans mon propre commentaire sur le fait de ne pas pouvoir passer des arguments à la chaîne connect. Voici une solution si vous avez besoin de se connecter dynamiquement à différentes bases de données à l'exécution. Je ne passe le nom de la base de données en tant que paramètre, mais des paramètres supplémentaires pourraient facilement être utilisés si nécessaire:

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
           /q/what-is-a-callable-in-python-25303/"""
        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))
18
répondu mwolfe02 2011-01-25 21:14:54

Cela fonctionne:

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

dans ce format, SQLAlchemy ignore simplement la chaîne de connexion et la transmet directement à pyodbc.

mise à jour:

Désolé, j'ai oublié que l'uri doit être encodé url, donc, les travaux suivants:

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()
5
répondu Singletoned 2011-03-03 15:17:08

Interne", mon.DB.server: 1433" est passé en tant que partie d'une chaîne de connexion comme SERVER=my.db.server:1433; .

malheureusement unixODBC / FreeTDS n'accepte pas un port dans le bit de serveur. Au lieu de cela il veut SERVER=my.db.server;PORT=1433;

pour utiliser la syntaxe sqlalchemy pour une chaîne de connexion, vous devez spécifier le port comme paramètre.

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

devient:

sqlalchemy.create_engine("mssql://myuser:mypwd@my.db.server/mydb?driver=FreeTDS&port=1433& odbc_options='TDS_Version=8.0'").connect()
4
répondu grapier 2013-10-19 19:08:37

pour passer divers paramètres à votre fonction connect, il sonne comme chaîne de format pourrait faire ce que vous voulez:

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))

et vous l'appelleriez alors avec quelque chose comme:

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

plus d'informations sur les chaînes de format est ici: http://docs.python.org/library/string.html#formatstrings

0
répondu skermajo 2010-12-22 01:59:00