SqlAlchemy équivalent de pyodbc connect ssortingng en utilisant FreeTDS

Les travaux suivants:

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

Les échecs suivants:

 import sqlalchemy sqlalchemy.create_engine("mssql://myuser:[email protected]:1433/mydb?driver=FreeTDS& odbc_options='TDS_Version=8.0'").connect() 

Le message d'erreur ci-dessus est:

DBAPIError: (Erreur) ('08001', '[08001] [unixODBC] [FreeTDS] [SQL Server] Impossible de se connecter à la source de données (0) (SQLDriverConnectW)') Aucun Aucun Aucun

Quelqu'un peut-il me diriger dans la bonne direction? Existe-t-il un moyen de dire simplement à sqlalchemy de passer une string de connection spécifique à pyodbc?

S'il vous plaît Note: Je veux garder ce DSN-less.

    L'exemple de @Singletoned ne fonctionnerait pas avec SQLAlchemy 0.7.2. À partir des documents SQLAlchemy pour la connection à SQL Server :

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

    Donc, pour le faire fonctionner, 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 également s'appliquer à 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é en cette ligne dans python3:

     quoted = urllib.parse.quote_plus 

    Je suis toujours intéressé par un moyen de le faire en une ligne dans l'instruction sqlalchemy create_engine , mais j'ai trouvé la solution de contournement suivante détaillée 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 transmettre d'arguments à la string de connection. Voici une solution générale si vous devez vous connecter dynamicment à différentes bases de données au moment de l'exécution. Je ne fais que passer le nom de la database en tant que paramètre, mais des parameters supplémentaires peuvent 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 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)) 

    Cela marche:

     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 string de connection et la transmet directement à pyodbc.

    Mettre à jour:

    Désolé, j'ai oublié que l'uri doit être encodé en URL, par conséquent, 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() 

    En interne "my.db.server: 1433" est passé dans le cadre d'une string de connection comme SERVER=my.db.server:1433; .

    Malheureusement, unixODBC / FreeTDS n'acceptera pas de port dans le bit SERVER. Au lieu de cela, il veut SERVER=my.db.server;PORT=1433;

    Pour utiliser la syntaxe sqlalchemy pour une string de connection, vous devez spécifier le port en tant que paramètre.

     sqlalchemy.create_engine("mssql://myuser:[email protected]:1433/mydb?driver=FreeTDS& odbc_options='TDS_Version=8.0'").connect() 

    devient:

     sqlalchemy.create_engine("mssql://myuser:[email protected]/mydb?driver=FreeTDS&port=1433& odbc_options='TDS_Version=8.0'").connect() 

    Pour passer divers parameters à votre fonction de connection, il semble que la string de format puisse 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 strings de format est ici: http://docs.python.org/library/ssortingng.html#formatssortingngs