代码改变世界

sqlalchemy源代码阅读随笔(1)

2017-08-10 16:39  很大很老实  阅读(1455)  评论(0编辑  收藏  举报

今天看的,是url.py模块,这个在create_engine中,起到的最用很大,其本质,就是对访问数据库的url,进行操作管里。我们可以直接访问这个类。

看一个简单的代码:

from sqlalchemy.engine import base, threadlocal, url

engineurl ='mysql+pymysql://root:root@192.168.31.196:3306/story_line_dev?charset=utf8'
u = url.make_url(engineurl)
print(u.__to_string__(hide_password=True))
反馈是:

D:\Python\Python35\python.exe C:/fitme/untitled/3.py
mysql+pymysql://root:***@192.168.31.196:3306/story_line_dev?charset=utf8

Process finished with exit code 0
正确的解析,并且按照要求把密码隐藏了。

第一步,看他的__init__

def __init__(self, drivername, username=None, password=None,
host=None, port=None, database=None, query=None):
self.drivername = drivername
self.username = username
self.password = password
self.host = host
if port is not None:
self.port = int(port)
else:
self.port = None
self.database = database
self.query = query or {}
这里实际上做了一个简单的判断等,比如对port等判断。基本上,我们很多时候,都是直接传入一个drivername,包含了所有的信息。

第二步,看上面提到的make_url方法:

def make_url(name_or_url):
"""Given a string or unicode instance, produce a new URL instance.

The given string is parsed according to the RFC 1738 spec. If an
existing URL object is passed, just returns the object.
"""

if isinstance(name_or_url, util.string_types):
return _parse_rfc1738_args(name_or_url)
else:
return name_or_url
def _parse_rfc1738_args(name):
pattern = re.compile(r'''
(?P<name>[\w\+]+)://
(?:
(?P<username>[^:/]*)
(?::(?P<password>.*))?
@)?
(?:
(?:
\[(?P<ipv6host>[^/]+)\] |
(?P<ipv4host>[^/:]+)
)?
(?::(?P<port>[^/]*))?
)?
(?:/(?P<database>.*))?
''', re.X)

m = pattern.match(name)
if m is not None:
components = m.groupdict()
if components['database'] is not None:
tokens = components['database'].split('?', 2)
components['database'] = tokens[0]
query = (
len(tokens) > 1 and dict(util.parse_qsl(tokens[1]))) or None
if util.py2k and query is not None:
query = {k.encode('ascii'): query[k] for k in query}
else:
query = None
components['query'] = query

if components['username'] is not None:
components['username'] = _rfc_1738_unquote(components['username'])

if components['password'] is not None:
components['password'] = _rfc_1738_unquote(components['password'])

ipv4host = components.pop('ipv4host')
ipv6host = components.pop('ipv6host')
components['host'] = ipv4host or ipv6host
name = components.pop('name')
return URL(name, **components)
else:
raise exc.ArgumentError(
"Could not parse rfc1738 URL from string '%s'" % name)
这个方法(_parse_rfc1738_args),对传入的url进行解析,找到各个部分。

然后返回的,是URL这个类的一个实例。