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: (Error) ('08001', '[08001] [unixODBC] [FreeTDS] [SQL Server] Impossible de se connecter à la source de données (0) (SQLDriverConnectW)') Aucun Aucun
Quelqu'un peut-il s'il vous plaît me diriger dans la bonne direction? Existe-t-il un moyen de dire simplement à sqlalchemy de transmettre une chaîne de connexion spécifique à pyodbc?
Veuillez noter: Je veux garder ce DSN-less.
L'exemple de @Singletoned ne fonctionnerait pas pour moi avec SQLAlchemy 0.7.2. À partir de documentation SQLAlchemy pour la connexion à 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.
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.
REMARQUE: Dans python 3, le module urllib a été divisé en parties et renommé. Ainsi, cette ligne dans python 2.7:
quoted = urllib.quote_plus
doit être remplacé par cette ligne en python3:
quoted = urllib.parse.quote_plus
Je suis toujours intéressé par un moyen de le faire en une seule ligne dans le sqlalchemy create_engine
instruction, 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 à un problème que j'ai soulevé dans mon propre commentaire concernant l'impossibilité de transmettre des arguments à la chaîne de connexion . Voici une solution générale si vous devez vous connecter dynamiquement à différentes bases de données au moment de l'exécution. Je ne transmets que le nom de la base de données en tant que paramètre, mais des paramètres supplémentaires pourraient facilement être utilisés au besoin:
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 chaîne de connexion et la transmet directement à pyodbc.
Mettre à jour:
Désolé, j'ai oublié que l'URI doit être encodé en URL, par conséquent, le fonctionnement suivant:
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 transmis dans le cadre d'une chaîne de connexion 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 chaîne de connexion, 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 paramètres à votre fonction de connexion, il semble que la chaîne de formatage fasse 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'appeleriez alors avec quelque chose comme:
connect('myserver', 'mydatabase', 'myuser', 'mypass')
Plus d'informations sur les chaînes de format sont ici: http://docs.python.org/library/string.html#formatstrings