python3.6“string%tuple”是做什么的?

2024-04-26 00:14:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在为一个基于Django的应用程序编写python模块,该应用程序通过cx\u Oracle访问Oracle数据库。django代码“似乎”有一个bug,破坏了cx\ U Oracle“executemany”方法的使用。如果我使用cx\u-Oracle并通过cx\u-Oracle严格打开连接,那么逻辑工作正常。如果通过django使用连接,则会失败。你知道吗

由于django是一个要求,我正在寻找一个解决办法,需要了解它失败的语句(下面)试图做什么。我知道“%”既可以用作模运算符,也可以用作字符串格式,就像在本例中一样。但是,尽管进行了大量搜索,但这似乎并不符合我能找到的任何使用“%”的字符串格式语法。有人能解释一下这是怎么回事吗?你知道吗

query = query % tuple(args)

TypeError: not all arguments converted during string formatting

其中:

query = 'INSERT INTO DATABASE.TABLE\n        (DATE, ID, COL_A, COL_B, COL_C)\n    VALUES (:1, :2, :3, :4, :5)\n'

args = [':arg0', ':arg1', ':arg2', ':arg3', ':arg4']

如果您在REPL中键入这些值和上面的语句,您将得到相同的错误。你知道吗

我知道我应该提交一份django bug报告。稍后会发现的。目前,我希望我能以某种方式更改查询字符串中的Oracle bind变量位置表示法,以满足上面的语句。同样,查询字符串直接与cx\u Oracle一起使用没有问题。你知道吗

详情:

Python 3.6.5::Anaconda公司

cx Oracle 7.0.0版

Django 2.0.7版

cx\ U Oracle查询格式: https://www.oracle.com/technetwork/articles/dsl/prez-python-queries-101587.html (见“一次多次”)

我的cx\U Oracle代码:

cursor = conn.cursor()
cursor.prepare(query)
cursor.executemany(query, list_of_tuples_of_values)
rows_affected = cursor.rowcount
conn.commit()

失败的代码在django模块中基本.py,第494行: (C:\python\Anaconda2\envs\py36\lib\site packages\django\db\backends\oracle)\基本.py)你知道吗

def _fix_for_params(self, query, params, unify_by_values=False):
    # cx_Oracle wants no trailing ';' for SQL statements.  For PL/SQL, it
    # it does want a trailing ';' but not a trailing '/'.  However, these
    # characters must be included in the original query in case the query
    # is being passed to SQL*Plus.
    if query.endswith(';') or query.endswith('/'):
        query = query[:-1]
    if params is None:
        params = []
    elif hasattr(params, 'keys'):
        # Handle params as dict
        args = {k: ":%s" % k for k in params}
        query = query % args
    elif unify_by_values and len(params) > 0:
        # Handle params as a dict with unified query parameters by their
        # values. It can be used only in single query execute() because
        # executemany() shares the formatted query with each of the params
        # list. e.g. for input params = [0.75, 2, 0.75, 'sth', 0.75]
        # params_dict = {0.75: ':arg0', 2: ':arg1', 'sth': ':arg2'}
        # args = [':arg0', ':arg1', ':arg0', ':arg2', ':arg0']
        # params = {':arg0': 0.75, ':arg1': 2, ':arg2': 'sth'}
        params_dict = {param: ':arg%d' % i for i, param in enumerate(set(params))}
        args = [params_dict[param] for param in params]
        params = {value: key for key, value in params_dict.items()}
        query = query % tuple(args)
    else:
        # Handle params as sequence
        args = [(':arg%d' % i) for i in range(len(params))]
        query = query % tuple(args)             <==============
    return query, self._format_params(params)

params = (datetime.datetime(2018, 10, 12, 0, 0), '123456', 10, 10, 8)

Tags: django字符串inforargsparamsquerycursor
2条回答

%string formatting operator,它将元组中的项值应用于它前面的格式字符串中的占位符(以%开头)。你知道吗

由于query字符串实际上不包含任何以%开头的格式占位符,%运算符失败,因为它无法在没有占位符的情况下将元组中的值映射到占位符。出于您的目的,您应该将args作为参数传递给数据库游标的execute方法,以便参数值可以安全地应用于绑定变量(在query字符串中由:1:2等表示)。你知道吗

为了实现跨数据库兼容性,Django在所有数据库后端使用统一的占位符。粘贴的代码将%s占位符转换为特定于Oracle的占位符,但由于查询已使用特定于Oracle的占位符,因此失败。你知道吗

%s替换占位符,应该可以:

 query = 'INSERT INTO DATABASE.TABLE\n        (DATE, ID, COL_A, COL_B, COL_C)\n    VALUES (%s, %s, %s, %s, %s)\n'

相关问题 更多 >