Skip to content

TypeError: not enough arguments for format string #3938

Closed
@sqlalchemy-bot

Description

@sqlalchemy-bot
Collaborator

Migrated issue, originally created by Sean Mars (@seanmars)

I get the "TypeError: not enough arguments for format string" when i execute by compiled object with mysql.dialect().

But when i execute by complied object without mysql.dialect(), it is fine.

Env:

  • MySQL 5.6
  • Python 3.5
    • PyMySQL==0.7.9
    • SQLAlchemy==1.1.6
from sqlalchemy import create_engine
from sqlalchemy import Table, MetaData, text
from sqlalchemy.dialects import mysql

# The score table just two filed id(vchar(20)), value(int)
engine = create_engine('mysql+pymysql://root:root@127.0.0.1/score?charset=utf8mb4')
conn = engine.connect()
meta = MetaData()
table = Table('score', meta, autoload=True, autoload_with=conn)
id = 1
value = 100
table.insert().values(id=id, value=value).compile(bind=conn, dialect=mysql.dialect())
conn.execute(ins)

Error log:

Traceback (most recent call last):
  File "/test/db/score.py", line 33, in insert
    conn.execute(ins)
  File "/test/venv/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 945, in execute
    return meth(self, multiparams, params)
  File "/test/venv/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", line 227, in _execute_on_connection
    return connection._execute_compiled(self, multiparams, params)
  File "/test/venv/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1075, in _execute_compiled
    compiled, parameters
  File "/test/venv/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1189, in _execute_context
    context)
  File "/test/venv/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1396, in _handle_dbapi_exception
    util.reraise(*exc_info)
  File "/test/venv/lib/python3.5/site-packages/sqlalchemy/util/compat.py", line 187, in reraise
    raise value
  File "/test/venv/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1182, in _execute_context
    context)
  File "/test/venv/lib/python3.5/site-packages/sqlalchemy/engine/default.py", line 470, in do_execute
    cursor.execute(statement, parameters)
  File "/test/venv/lib/python3.5/site-packages/pymysql/cursors.py", line 164, in execute
    query = self.mogrify(query, args)
  File "/test/venv/lib/python3.5/site-packages/pymysql/cursors.py", line 143, in mogrify
    query = query % self._escape_args(args, conn)
TypeError: not enough arguments for format string

Activity

sqlalchemy-bot

sqlalchemy-bot commented on Mar 14, 2017

@sqlalchemy-bot
CollaboratorAuthor

Changes by Sean Mars (@seanmars):

  • added labels: mysql
sqlalchemy-bot

sqlalchemy-bot commented on Mar 14, 2017

@sqlalchemy-bot
CollaboratorAuthor

Changes by Sean Mars (@seanmars):

  • set milestone to "1.1.x"
sqlalchemy-bot

sqlalchemy-bot commented on Mar 14, 2017

@sqlalchemy-bot
CollaboratorAuthor

Changes by Sean Mars (@seanmars):

  • edited description
sqlalchemy-bot

sqlalchemy-bot commented on Mar 14, 2017

@sqlalchemy-bot
CollaboratorAuthor

Michael Bayer (@zzzeek) wrote:

hello -

this is not enough detail. Please provide a complete mcve illustrating necessary details including what this table looks like, what "conn" is, stack trace, anything. thanks.

sqlalchemy-bot

sqlalchemy-bot commented on Mar 15, 2017

@sqlalchemy-bot
CollaboratorAuthor

Sean Mars (@seanmars) wrote:

Hi,

I forgot completed the code. Updated.

Thanks.

sqlalchemy-bot

sqlalchemy-bot commented on Mar 15, 2017

@sqlalchemy-bot
CollaboratorAuthor

Changes by Sean Mars (@seanmars):

  • edited description
sqlalchemy-bot

sqlalchemy-bot commented on Mar 15, 2017

@sqlalchemy-bot
CollaboratorAuthor

Changes by Sean Mars (@seanmars):

  • edited description
sqlalchemy-bot

sqlalchemy-bot commented on Mar 15, 2017

@sqlalchemy-bot
CollaboratorAuthor

Changes by Sean Mars (@seanmars):

  • removed milestone (was: "1.1.x")
sqlalchemy-bot

sqlalchemy-bot commented on Mar 15, 2017

@sqlalchemy-bot
CollaboratorAuthor

Changes by Sean Mars (@seanmars):

  • edited description
sqlalchemy-bot

sqlalchemy-bot commented on Mar 15, 2017

@sqlalchemy-bot
CollaboratorAuthor

Michael Bayer (@zzzeek) wrote:

Why do you need to execute a compiled object directly?

sqlalchemy-bot

sqlalchemy-bot commented on Mar 15, 2017

@sqlalchemy-bot
CollaboratorAuthor

Michael Bayer (@zzzeek) wrote:

Recent versions of pymysql report the paramstyle as "pyformat", whereas the default for a plain vanilla mysql dialect is "format". the "pyformat" doesn't come in until the module is imported which is not happening because you are splitting out between two different dialects, the one in your engine, and the one in your compilation, and the system looks at the dialect paramstyle and not that of the "compiled" object when organizing the bound parameters. it only "works" because pymysql actually accepts multiple paramstyles. I guess we can change the executor to check compiled.positional in this one case. But this is an odd use case and you probably don't need to be executing compiled objects directly (alas it's part of the public API).

sqlalchemy-bot

sqlalchemy-bot commented on Mar 15, 2017

@sqlalchemy-bot
CollaboratorAuthor

Michael Bayer (@zzzeek) wrote:

diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py
index b8c2d28..3968663 100644
--- a/lib/sqlalchemy/engine/default.py
+++ b/lib/sqlalchemy/engine/default.py
@@ -627,7 +627,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
         # into a dict or list to be sent to the DBAPI's
         # execute() or executemany() method.
         parameters = []
-        if dialect.positional:
+        if compiled.positional:
             for compiled_params in self.compiled_parameters:
                 param = []
                 for key in self.compiled.positiontup:

sqlalchemy-bot

sqlalchemy-bot commented on Mar 15, 2017

@sqlalchemy-bot
CollaboratorAuthor

Changes by Michael Bayer (@zzzeek):

  • added labels: low priority
sqlalchemy-bot

sqlalchemy-bot commented on Mar 15, 2017

@sqlalchemy-bot
CollaboratorAuthor

Changes by Michael Bayer (@zzzeek):

  • set milestone to "1.2"
sqlalchemy-bot

sqlalchemy-bot commented on Mar 15, 2017

@sqlalchemy-bot
CollaboratorAuthor

Michael Bayer (@zzzeek) wrote:

so I don't know what your goal is, but for now, you need to use the right paramstyle, so if you must use different dialects you need to pass that through:

id = 1
value = 100
ins = table.insert().values(id=id, value=value).compile(
    bind=conn, dialect=mysql.dialect(paramstyle=engine.dialect.paramstyle))
conn.execute(ins)

passing the engine/connection to compile() is all that's needed however to get the correct dialect. there's no need to pass dialect at all if the connection is present.

8 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @sqlalchemy-bot

        Issue actions

          TypeError: not enough arguments for format string · Issue #3938 · sqlalchemy/sqlalchemy