开发者

how to use mysql defaults file (my.cnf) with sqlalchemy?

开发者 https://www.devze.com 2023-02-17 17:48 出处:网络
I\'d like to have sqlalchemy get the hostname, username, and password for the mysql database it\'s connecting to.

I'd like to have sqlalchemy get the hostname, username, and password for the mysql database it's connecting to.

The documentation says mysql schemas are specified as such:

mysql_db = create_engine('mysql://scott:tiger@localhost/foo')

Is it possible to instead sourc开发者_高级运维e a mysql defaults file such as /etc/my.cnf and get the login details from there? I'd like to avoid embedding the username/password in my code.


Here is a result that was found on the sqlalchemy mailing list, posted by Tom H:

http://www.mail-archive.com/sqlalchemy@googlegroups.com/msg11241.html

from sqlalchemy.engine.url import URL

myDB = URL(drivername='mysql', host='localhost',
    database='my_database_name',
    query={ 'read_default_file' : '/path/to/.my.cnf' }
)
engine = create_engine(name_or_url=myDB)
# use the engine as usual, no password needed in your code file :)


If you want to use MySQLdb you could parse the ini file with ConfigParser:

sql_ini_fileparser = ConfigParser.RawConfigParser()
sql_ini_fileparser.read('example.cfg')
user = sql_ini_fileparser.get('client', 'user')
password = sql_ini_fileparser.get('client', 'password')


This is an old question, but the accepted answer still forces you to include the hostname as a string. I was looking for a solution that reads the my.cnf file and gets the hostname from there as well.

The first thing I found was this page, and the suggestion to build the URL using the query={'read_default_file': 'my.cnf'} keyword. The following are all equivalent to his answer, and they all require you to pass in the hostname explicitly, but at least you can get passwords, ports, charset, and other things from the my.cnf file

engine = create_engine('mysql+pymysql://hostname', connect_args={'read_default_file': 'mu.cnf'})
engine = create_engine('mysql+pymysql://hostname?read_default_file=my.cnf')

After reading much of the source code, I believe there is no possible way to get a sqlalchemy engine without passing the hostname into create_engine somehow.

So somehow you have to get the hostname from somewhere else. The simplest options for this are to use an environment variable ie host=os.getenv('DATABASE_URI') or to parse a config file using the configparser library like karlo suggested. I prefer the config file because then you don't have to inject usernames and passwords into environment variables - here's roughly how pymysql parses the file in the source code for pymysql.connections.Connection

from configparser import Parser

read_default_group = 'client' # replace this if you're super special
read_default_file = '/etc/my.cnf' # replace this with the path you want to use

cfg = Parser()
cfg.read(defaults_file) 

def _config(key, arg=None):
    try:
        return cfg.get(read_default_group, key)
    except Exception:
        return arg

user = _config("user")
password = _config("password")
host = _config("host")
database = _config("database")
port = int(_config("port", 3306))
charset = _config("charset", "utf8mb4")
engine = create_engine(f'mysql+pymysql://{user}:{password}@{host}:{port}/{database}?charset={charset}')


I know this is an old thread, but the solutions mentioned above would not work for me when attempting to do this as I was connecting via a socket in the cnf file.

Instead, I have done the following which works:

First off I parse the cnf file to get the username and password.

CnfFile = open('/directory/.MyCnfFile.cnf', 'r')
for Line in CnfFile:
    if Line.startswith("user"):
        User = Line.lstrip("user=")
        User = User.rstrip("\n")
    if Line.startswith("password"):
        Password = Line.lstrip("password=")
        Password = Password.rstrip("\n")

I then create the engine using the socket.

engine = create_engine("mysql+pymysql://"+User+":"+Password+"@localhost?unix_socket=/var/run/mysqld/mysqld-socket.sock")
0

精彩评论

暂无评论...
验证码 换一张
取 消