MySQL Connector for Python - python

I am using mysql.connector for Python. Below are my connection parameters. How can I set a timeout or increase the default timeout?
class Config(object):
"""Configure me so examples work
Use me like this:
mysql.connector.Connect(**Config.dbinfo())
"""
HOST = dbhost
DATABASE = dbdatabase
USER = dbusername
PASSWORD = dbpassword
PORT = 3306
CHARSET = 'utf8'
UNICODE = True
WARNINGS = True
#classmethod
def dbinfo(cls):
return {
'host': cls.HOST,
'port': cls.PORT,
'database': cls.DATABASE,
'user': cls.USER,
'password': cls.PASSWORD,
'charset': cls.CHARSET,
'use_unicode': cls.UNICODE,
'get_warnings': cls.WARNINGS,
}

According to MySQL Connector/Python :: 6 Connector/Python Connection Arguments in the official documentation:
To set a timeout value for connections, use connection_timeout.

If you are using mysql.connector.connect to connect with DB you can simply use connection_timeout parameter to define a timeout externally make sure value given will be in seconds instead of milliseconds.
conn = mysql.connector.connect(
pool_name=pool['name'],
pool_size=pool['size'],
host=config['host'],
port=config['port'],
user=config['user'],
passwd=config['passwd'],
db=config['db'],
charset=config['charset'],
use_unicode=True,
connection_timeout=10
)

I found something here: http://dev.mysql.com/doc/refman/5.5/en/connector-python-connectargs.html
I think you are looking for the parameter
connection_timeout (connect_timeout*)

This works for me:
conn = mysql.connector.connect(
pool_name=pool['name'],
pool_size=pool['size'],
host=config['host'],
port=config['port'],
user=config['user'],
passwd=config['passwd'],
db=config['db'],
charset=config['charset'],
use_unicode=True,
connect_timeout=1000
)
If you use MySQLdb:
conn = MySQLdb.connect(
host=config['host'],
port=config['port'],
user=config['user'],
passwd=config['passwd'],
db=config['db'],
charset=config['charset'],
use_unicode=True,
connect_timeout=1000
)

Related

How to connect to Oracle-RAC using SCAN in python?

I use cx_Oracle module to connect to standalone Oracle server as follows
import cx_Oracle
CONN_INFO = {
'host': 'xxx.xx.xxx.x',
'port': 12345,
'user': 'user_name',
'psw': 'your_password',
'service': 'abc.xyz.com',
}
CONN_STR = '{user}/{psw}#{host}:{port}/{service}'.format(**CONN_INFO)
connection = cx_Oracle.connect(CONN_STR)
but as scan IP doesn not have machine and its own username passoword, How do we connect?
Es described in the documentation, you can simple use the name defined in tnsnames.ora.
Say your RAC tnsnames entry is called MAXIMIR than you can connect with
con = cx_Oracle.connect("my_usr", "my_pwd", "MAXIMIR", encoding="UTF-8")
alternatively you may pass the whole connection string in a dns variable
dsn = """(DESCRIPTION=
(FAILOVER=on)
(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=tcp)(HOST=scan1)(PORT=1521))
(ADDRESS=(PROTOCOL=tcp)(HOST=scan2)(PORT=1521)))
(CONNECT_DATA=(SERVICE_NAME=MAXIMIR)))"""
connection = cx_Oracle.connect("my_usr", "my_pwd", dsn, encoding="UTF-8")

How to pass basic authentication in mysqldb python package?

db = sql.connect(host,"username","password","dbname", basic_auth=('test', 'test'))
here is an example for mysql connector:
https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html
In MySQLdb, you can use the connect() function to create a connection to the database. It has various parameters to it, which you can see in the link here: http://structure.usc.edu/mysqldb/MySQLdb-3.html.
There is no parameter called basic_auth (which you have used in your code) in the list of parameters.
MySQLdb uses the username and password that you specify to authenticate. Here is an example:
import MySQLdb
connection = MySQLdb.connect(host = '127.0.0.1', user = 'root', passwd = 'test')

Oracle connection string with at sign # in pasword

I have a code that connect to oracle using connection string:
conn = cx_Oracle.connect('username/password#server:port/services')
But the problem is my password contain # character so it may become
conn = cx_Oracle.connect('username/p#ssword#server:port/services')
it return
DatabaseError: ORA-12154: TNS:could not resolve the connect identifier
specified
I use Django with Oracle with this settings
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.oracle',
'NAME': 'Services',
'USER': 'user',
'PASSWORD': 'p#ssword',
'HOST': 'ip',
'PORT': 'port',
}
}
I cant change password :( Does anyone know this problem?
I haven't tried cx_Oracle, but you might be able to connect by specifying the individual parameters -
conn = cx_Oracle.connect(user='username', password='p#ssword', dsn='server:port/services')
OR
dsn_tns = cx_Oracle.makedsn('server', 'port', 'services')
conn = cx_Oracle.connect(user='username', password='p#ssword', dsn=dsn_tns)
You can use any of the following way based on Service Name or SID whatever you have.
With SID:
dsn_tns = cx_Oracle.makedsn('server', 'port', 'sid')
conn = cx_Oracle.connect(user='username', password='p#ssword', dsn=dsn_tns)
OR
With Service Name:
dsn_tns = cx_Oracle.makedsn('server', 'port', service_name='service_name')
conn = cx_Oracle.connect(user='username', password='p#ssword', dsn=dsn_tns)
Does this work?
conn = cx_Oracle.connect('username/"p#ssword"#server:port/services')
FYI: This was a long-standing bug in Django. The first stable version containing the fix is v2.1
All the answers mentioned here did not work for SQLAlchemy.
Parsing the characters to create a valid URL worked:
from sqlalchemy.engine import create_engine
import urllib.parse
url_password = urllib.parse.quote_plus(password)
connection_string = f"oracle+cx_oracle://{username}:{url_password}#{server}:{port}/?service_name={service}"
connection = create_engine(connection_string)
Should probably do the same with the other components of the connection string.

How to make mysql connection that requires CA-CERT with sqlalchemy or SQLObject

I would like to connect to a MySQL database that requires ca-cert. I can do it with MySQLdb like below:
MySQLdb.connect(host = self.host,
port = self.port,
unix_socket = self.unix_socket,
user = self.user,
passwd = self.passwd,
db = self.db,
ssl = { 'cert': self.sslcert,
'key': self.sslkey,
'ca': self.sslca }
How do I do the same think in SQLAlchemy or SQLObject?
Thanks,
peter
To use SSL certs with SQLAlchemy and MySQLdb, use the following python code:
db_connect_string='mysql://<user>:<pswd>#<db server>:3306/<database>'
ssl_args = {'ssl': {'cert':'/path/to/client-cert',
'key':'/path/to/client-key',
'ca':'/path/to/ca-cert'}}
create_engine(db_connect_string, connect_args=ssl_args)
create_engine() in SQLAlchemy has a connect_args parameter:
connect_args – a dictionary of options which will be passed directly
to the DBAPI’s connect() method as additional keyword arguments.
SQLObject (untested):
from sqlobject.mysql import MySQLConnection
connection = MySQLConnection(
db=self.db,
user=self.user,
password=self.password,
host=self.host,
ssl_key=self.sslkey,
ssl_cert=self.sslcert,
ssl_ca=self.sslca,
)
According to their docs, SQLAlchemy's create_engine function takes a db url with the following format: dialect[+driver]://user:password#host/dbname[?key=value..] meaning you could pass the ssl key, cert, and ca as key value pairs.

Python idiom for 'Try until no exception is raised'

I want my code to automatically try multiple ways to create a database connection. As soon as one works, the code needs to move on (i.e. it shouldn't try to other ways anymore). If they all fail well, then the script can just blow up.
So in - what I thought was, but most likely isn't - a stroke of genius I tried this:
import psycopg2
from getpass import getpass
# ouch, global variable, ooh well, it's just a simple script eh
CURSOR = None
def get_cursor():
"""Create database connection and return standard cursor."""
global CURSOR
if not CURSOR:
# try to connect and get a cursor
try:
# first try the bog standard way: db postgres, user postgres and local socket
conn = psycopg2.connect(database='postgres', user='postgres')
except psycopg2.OperationalError:
# maybe user pgsql?
conn = psycopg2.connect(database='postgres', user='pgsql')
except psycopg2.OperationalError:
# maybe it was postgres, but on localhost? prolly need password then
conn = psycopg2.connect(database='postgres', user='postgres', host='localhost', password=getpass())
except psycopg2.OperationalError:
# or maybe it was pgsql and on localhost
conn = psycopg2.connect(database='postgres', user='pgsql', host='localhost', password=getpass())
# allright, nothing blew up, so we have a connection
# now make a cursor
CURSOR = conn.cursor()
# return existing or new cursor
return CURSOR
But it seems that the second and subsequent except statements aren't catching the OperationalErrors anymore. Probably because Python only catches an exception once in a try...except statement?
Is that so? If not: is there anything else I'm doing wrong? If so: how do you do something like this then? Is there a standard idiom?
(I know there are ways around this problem, like having the user specify the connection parameters on the command line, but that's not my question ok :) )
EDIT:
I accepted retracile's excellent answer and I took in gnibbler's comment for using the for..else construct. The final code became (sorry, I'm not really following the max characters per line limit from pep8):
EDIT 2: As you can see from the comment on the Cursor class: I don't really know how to call this kind of class. It's not really a singleton (I can have multiple different instances of Cursor) but when calling get_cursor I do get the same cursor object everytime. So it's like a singleton factory? :)
import psycopg2
from getpass import getpass
import sys
class UnableToConnectError(Exception):
pass
class Cursor:
"""Cursor singleton factory?"""
def __init__(self):
self.CURSOR = None
def __call__(self):
if self.CURSOR is None:
# try to connect and get a cursor
attempts = [
{'database': 'postgres', 'user': 'postgres'},
{'database': 'postgres', 'user': 'pgsql'},
{'database': 'postgres', 'user': 'postgres', 'host': 'localhost', 'password': None},
{'database': 'postgres', 'user': 'pgsql', 'host': 'localhost', 'password': None},
]
for attempt in attempts:
if 'password' in attempt:
attempt['password'] = getpass(stream=sys.stderr) # tty and stderr are default in 2.6, but 2.5 uses sys.stdout, which I don't want
try:
conn = psycopg2.connect(**attempt)
attempt.pop('password', None)
sys.stderr.write("Succesfully connected using: %s\n\n" % attempt)
break # no exception raised, we have a connection, break out of for loop
except psycopg2.OperationalError:
pass
else:
raise UnableToConnectError("Unable to connect: exhausted standard permutations of connection dsn.")
# allright, nothing blew up, so we have a connection
# now make a cursor
self.CURSOR = conn.cursor()
# return existing or new cursor
return self.CURSOR
get_cursor = Cursor()
Approximately:
attempts = [
{ 'database'='postgres', 'user'='pgsql', ...},
{ 'database'='postgres', 'user'='postgres', 'host'='localhost', 'password'=getpass()},
...
]
conn = None
for attempt in attempts:
try:
conn = psycopg2.connect(**attempt)
break
except psycopg2.OperationalError:
pass
if conn is None:
raise a ruckus
CURSOR = conn.cursor()
Now, if you don't want to call getpass() unless it is necessary, you'd want to check if 'password' in attempt: attempt['password'] = getpass() or so.
Now about that global....
class MyCursor:
def __init__(self):
self.CURSOR = None
def __call__(self):
if self.CURSOR is None:
<insert logic here>
return self.CURSOR
get_cursor = MyCursor()
... though I think there are a couple of other ways to accomplish the same thing.
Bringing it all together:
class MyCursor:
def __init__(self):
self.CURSOR = None
def __call__(self):
if self.CURSOR is None:
attempts = [
{'database'='postgres', 'user'='postgres'},
{'database'='postgres', 'user'='pgsql'},
{'database'='postgres', 'user'='postgres', 'host'='localhost', 'password'=True},
{'database'='postgres', 'user'='pgsql', 'host'='localhost', 'password'=True},
]
conn = None
for attempt in attempts:
if 'password' in attempt:
attempt['password'] = getpass()
try:
conn = psycopg2.connect(**attempt)
break # that didn't throw an exception, we're done
except psycopg2.OperationalError:
pass
if conn is None:
raise a ruckus # nothin' worked
self.CURSOR = conn.cursor()
return self.CURSOR
get_cursor = MyCursor()
Note: completely untested
You're close. Probably the best thing to do in this case is nesting the second and subsequent attempts in the except block. Thus the critical part of your code would look like:
if not CURSOR:
# try to connect and get a cursor
try:
# first try the bog standard way: db postgres, user postgres and local socket
conn = psycopg2.connect(database='postgres', user='postgres')
except psycopg2.OperationalError:
# maybe user pgsql?
try:
conn = psycopg2.connect(database='postgres', user='pgsql')
except psycopg2.OperationalError:
# maybe it was postgres, but on localhost? prolly need password then
try:
conn = psycopg2.connect(database='postgres', user='postgres', host='localhost', password=getpass())
except psycopg2.OperationalError:
# or maybe it was pgsql and on localhost
conn = psycopg2.connect(database='postgres', user='pgsql', host='localhost', password=getpass())

Categories

Resources