Уведомления

Группа в Telegram: @pythonsu

#1 Июль 12, 2011 15:18:04

memba
От:
Зарегистрирован: 2010-12-01
Сообщения: 43
Репутация: +  0  -
Профиль   Отправить e-mail  

Передача параметров в execute

Добрый день.

Использую Python 3.1.

Перестали работать передача параметров в метод execute. Что делаю:

# -*- coding: utf-8 -*-

import MySQLdb

try:
con = MySQLdb.connect(host="localhost", user="root", passwd="5213", db="test")
cur = con.cursor()
cur.execute('SET NAMES `utf8`')
cur.execute("""SELECT `name` FROM `city` WHERE `id_city`=%d""", (1,))
for row in cur:
print(row[0])
except MySQLdb.Error:
print(con.error())
Выдает сообщение об ошибке:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘%d’ at line 1

Посмотрел значение переменной MySQLdb.paramstyle, и она равна format. Значит для замены нужно использовать формат в стиле printf

Проверил ещё на всякий случай:

cur.execute("""SELECT `name` FROM `city` WHERE `id_city`=?""", (1,))
cur.execute("""SELECT `name` FROM `city` WHERE `id_city`=(%(ids)d)""", { 'ids': 1 })
Что-то я ничего не понимаю.



Офлайн

#2 Июль 12, 2011 17:10:54

memba
От:
Зарегистрирован: 2010-12-01
Сообщения: 43
Репутация: +  0  -
Профиль   Отправить e-mail  

Передача параметров в execute

Установил Python 2.7 и в нём замечательно работает.

Посмотрел что в реализации модуля.

MySQLdb для Python 2.7

def execute(self, query, args=None):

"""Execute a query.

query -- string, query to execute on server
args -- optional sequence or mapping, parameters to use with query.

Note: If args is a sequence, then %s must be used as the
parameter placeholder in the query. If a mapping is used,
%(key)s must be used as the placeholder.

Returns long integer rows affected, if any

"""
del self.messages[:]
db = self._get_db()
charset = db.character_set_name()
if isinstance(query, unicode):
query = query.encode(charset)
if args is not None:
query = query % db.literal(args)
try:
r = self._query(query)
except TypeError, m:
if m.args[0] in ("not enough arguments for format string",
"not all arguments converted"):
self.messages.append((ProgrammingError, m.args[0]))
self.errorhandler(self, ProgrammingError, m.args[0])
else:
self.messages.append((TypeError, m))
self.errorhandler(self, TypeError, m)
except:
exc, value, tb = sys.exc_info()
del tb
self.messages.append((exc, value))
self.errorhandler(self, exc, value)
self._executed = query
if not self._defer_warnings: self._warning_check()
return r
MySQLdb для Python 3.1

def execute(self, query, args=None):

"""Execute a query.

query -- string, query to execute on server
args -- optional sequence or mapping, parameters to use with query.

Note: If args is a sequence, then %s must be used as the
parameter placeholder in the query. If a mapping is used,
%(key)s must be used as the placeholder.

Returns long integer rows affected, if any

"""
del self.messages[:]
db = self._get_db()
charset = db.character_set_name()

if args is not None:
if isinstance(query, bytes):
query = query.decode();

if isinstance(args, dict):
query = query.format( **db.literal(args) )
elif isinstance(args, tuple) or isinstance(args, list):
query = query.format( *db.literal(args) )
else:
query = query.format( db.literal(args) )

if isinstance(query, str):
query = query.encode(charset);

try:
r = self._query(query)
except TypeError as m:
if m.args[0] in ("not enough arguments for format string",
"not all arguments converted"):
self.messages.append((ProgrammingError, m.args[0]))
self.errorhandler(self, ProgrammingError, m.args[0])
else:
self.messages.append((TypeError, m))
self.errorhandler(self, TypeError, m)
except:
exc, value, tb = sys.exc_info()
del tb
self.messages.append((exc, value))
self.errorhandler(self, exc, value)
self._executed = query
if not self._defer_warnings: self._warning_check()
return r
Обработка вообще отличается, только не понятно почему не работает.



Офлайн

#3 Июль 12, 2011 17:40:02

agalen
От:
Зарегистрирован: 2011-03-23
Сообщения: 185
Репутация: +  17  -
Профиль   Отправить e-mail  

Передача параметров в execute

Судя по коду в 3.x используется метод format, который требует другой способ задания параметров (через фигурные скобки).
А вот в док-строке у метода execute указаны старые данные.
И вообще, насколько я помню, в версии 3 оператор % для строк считается deprecated.



Офлайн

#4 Июль 12, 2011 17:48:43

memba
От:
Зарегистрирован: 2010-12-01
Сообщения: 43
Репутация: +  0  -
Профиль   Отправить e-mail  

Передача параметров в execute

Почему через фигурные?

if isinstance(args, dict):
query = query.format( **db.literal(args) )
elif isinstance(args, tuple) or isinstance(args, list):
query = query.format( *db.literal(args) )
else:
query = query.format( db.literal(args) )
Может быть Словарь, Кортеж, Список или просто строка. Реализация метода db.literal одинакова в обеих версиях.

** и * новая фича в Python 3.* распаковывает словарь и список



Офлайн

#5 Июль 12, 2011 17:57:33

memba
От:
Зарегистрирован: 2010-12-01
Сообщения: 43
Репутация: +  0  -
Профиль   Отправить e-mail  

Передача параметров в execute

Всё, я расковырял модуль, подзабыл я про обращение с методов format

cur.execute('SELECT name FROM city WHERE id_city={0}', 1)
cur.execute('SELECT name FROM city WHERE id_city={0:s}', 1)
cur.execute('SELECT name FROM city WHERE id_city={0}', (1,))
Ну и т.к. так же со списком и словарём

Работает.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version