当密码包含特殊字符时,如何编写连接字符串

108

我正在使用SQLalchemy开发Python项目,我想要一个整洁的连接字符串来访问我的数据库。例如:

engine = create_engine('postgresql://user:pass@host/database')

问题在于我的密码包含一系列特殊字符,当我尝试连接时,它们被解释为分隔符。

我意识到我可以使用 engine.URL.create() ,然后像这样传递我的凭据:

import sqlalchemy as sa

connection_url = sa.engine.URL.create(
    drivername="postgresql",
    username="user",
    password="p@ss",
    host="host",
    database="database",
)
print(connection_url)
# postgresql://user:p%40ss@host/database

但如果可能的话,我更愿意使用连接字符串。

所以明确一下,是否可能编码我的连接字符串,或者连接字符串中的密码部分 - 以便可以正确解析?


你能举个例子说明哪些特殊字符不能通过反斜杠进行转义吗? - tuergeist
连接信息中“X6~k9?q”后缺少“=”。 - KeyboardInterrupt
无论我是否转义,这都会发生。 - KeyboardInterrupt
@KeyboardInterrupt 你能解决这个问题吗?谢谢。 - Tanu
2
“我意识到我可以使用 engine.URL.create() 然后传递我的凭据”,未来的读者不应忽略这确实是创建连接URL的首选方法。 - Gord Thompson
3个回答

169

你需要对连接字符串中的密码部分进行URL编码:

from urllib.parse import quote_plus
from sqlalchemy.engine import create_engine
engine = create_engine("postgres://user:%s@host/database" % quote_plus("p@ss"))

如果你查看SQLAlchemy中用于表示数据库连接URL的类的实现(在sqlalchemy/engine/url.py中),你会发现他们在将URL实例转换为字符串时使用相同的方法来转义密码。


1
使用unquote_plus的部分显然是一个错误,并在v0.9.0中进行了更改(参考) - 2013年12月。有趣的是,他们仍然使用quote_plus进行引用,但使用unquote进行取消引用,因此可能仍然存在一些错误(来源)。 - wim
救命稻草!!! :D - undefined

44

在Python 3.x中,您需要导入urllib.parse.quote:

在Python 3中,urllib模块被拆分成几个部分,并改名为urllib.request、urllib.parse和urllib.error。

当您尝试使用包含特殊字符序列的密码连接MySQL数据库且您的Python版本为Python3时:

user_name是您的数据库用户ID。
database是您的数据库名称。
your_password是包含特殊字符的密码。


 from urllib.parse import quote  
 from sqlalchemy.engine import create_engine
 engine = create_engine('mysql+mysqlconnector://user_name:%s@localhost:3306/database' % quote('your_password'))

1
如果密码中包含 @,则无法正常工作。 - Tanu
谭努,报价将把“@”更改为“%40”。 - undefined

9

方法1:

密码中包含"@"字符,您可以使用"%40"代替来转义该字符。

更改前:

# mssql+pymssql://username:password@databaseserver/database

mssql+pymssql://admin:admin123@10.10.10.110/dbtest

之后:

mssql+pymssql://admin:admin%40123@10.10.10.110/dbtest

方法2:

使用urllib.parse.quote_plus对密码进行编码。

DATABASE_PASSWORD = "admin@123"

# to elimate the error, if the password contains special characters like '@' 
DATABASE_PASSWORD_UPDATED = urllib.parse.quote_plus(DATABASE_PASSWORD)

以下是完整的代码片段:

import os, sys, click, urllib
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text

# Make sure to replace below data with your DB values
DATABASE_HOST = "10.10.10.110"
DATABASE_NAME = "dbtest"
DATABASE_USERNAME = "admin" 
DATABASE_PASSWORD = "admin@123"

app = Flask(__name__)

# to elimate the error, if the password contains special characters like '@'
# replace the DATABASE_PASSWORD with DATABASE_PASSWORD_UPDATED. 

DATABASE_PASSWORD_UPDATED = urllib.parse.quote_plus(DATABASE_PASSWORD)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mssql+pymssql://'+DATABASE_USERNAME+':'+DATABASE_PASSWORD_UPDATED+'@'+DATABASE_HOST+'/'+DATABASE_NAME
app.config['SQLALCHEMY_ECHO'] = True


db = SQLAlchemy(app)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接