我真的希望能够为我的应用程序打印出有效的SQL,包括值,而不是绑定参数,但是在SQLAlChemy中如何做到这一点并不明显(根据设计,我相当确定).

有没有人用一般的方法解决了这个问题?

推荐答案

This works in python 2 and 3 and is a bit cleaner than before, but requires SA>=1.0.

from sqlalchemy.engine.default import DefaultDialect
from sqlalchemy.sql.sqltypes import String, DateTime, NullType

# python2/3 compatible.
PY3 = str is not bytes
text = str if PY3 else unicode
int_type = int if PY3 else (int, long)
str_type = str if PY3 else (str, unicode)


class StringLiteral(String):
    """Teach SA how to literalize various things."""
    def literal_processor(self, dialect):
        super_processor = super(StringLiteral, self).literal_processor(dialect)

        def process(value):
            if isinstance(value, int_type):
                return text(value)
            if not isinstance(value, str_type):
                value = text(value)
            result = super_processor(value)
            if isinstance(result, bytes):
                result = result.decode(dialect.encoding)
            return result
        return process


class LiteralDialect(DefaultDialect):
    colspecs = {
        # prevent various encoding explosions
        String: StringLiteral,
        # teach SA about how to literalize a datetime
        DateTime: StringLiteral,
        # don't format py2 long integers to NULL
        NullType: StringLiteral,
    }


def literalquery(statement):
    """NOTE: This is entirely insecure. DO NOT execute the resulting strings."""
    import sqlalchemy.orm
    if isinstance(statement, sqlalchemy.orm.Query):
        statement = statement.statement
    return statement.compile(
        dialect=LiteralDialect(),
        compile_kwargs={'literal_binds': True},
    ).string

演示:

# coding: UTF-8
from datetime import datetime
from decimal import Decimal

from literalquery import literalquery


def test():
    from sqlalchemy.sql import table, column, select

    mytable = table('mytable', column('mycol'))
    values = (
        5,
        u'snowman: ☃',
        b'UTF-8 snowman: \xe2\x98\x83',
        datetime.now(),
        Decimal('3.14159'),
        10 ** 20,  # a long integer
    )

    statement = select([mytable]).where(mytable.c.mycol.in_(values)).limit(1)
    print(literalquery(statement))


if __name__ == '__main__':
    test()

给出以下输出:(在python 2.7和3.4中测试)

SELECT mytable.mycol
FROM mytable
WHERE mytable.mycol IN (5, 'snowman: ☃', 'UTF-8 snowman: ☃',
      '2015-06-24 18:09:29.042517', 3.14159, 100000000000000000000)
 LIMIT 1

Python相关问答推荐

双情节在单个图上切换-pPython

Python:MultiIndex Dataframe到类似json的字典列表

是否有方法将现有的X-Y图转换为X-Y-Y1图(以重新填充)?

按 struct 值对Polars列表[struct[]]排序

Altair -箱形图边界设置为黑色,中线设置为红色

Polars Select 多个元素产品

Plotly:如何更改Heatmap中彩色条的勾选文本

如何使用Selenium访问svg对象内部的元素

Tkinter滑动条标签.我不确定如何删除滑动块标签或更改其文本

Pydantic:如何将对象列表表示为dict(将列表序列化为dict)

三个给定的坐标可以是矩形的点吗

我们可以为Flask模型中的id字段主键设置默认uuid吗

如何在给定的条件下使numpy数组的计算速度最快?

海上重叠直方图

所有列的滚动标准差,忽略NaN

删除marplotlib条形图上的底边

如何在两列上groupBy,并使用pyspark计算每个分组列的平均总价值

找到相对于列表索引的当前最大值列表""

Python—压缩叶 map html作为邮箱附件并通过sendgrid发送

PYTHON、VLC、RTSP.屏幕截图不起作用