[英]Can I combine python's `for` statement with SQL like this: `for id, name, ctime in db.select('table_name', where='…')`
So I'm accessing MySQL from python 2.7 scripts, now I can do this: 因此,我正在从python 2.7脚本访问MySQL,现在可以执行以下操作:
for id, name, area in db.select('SELECT id, name, area'
' FROM some_table'
' WHERE area IS NOT NULL'):
print id, name, area
But the duplicate variables id, name, area
of the for statement and those in the select statement are eating me up. 但是重复的变量
id, name, area
for语句的id, name, area
以及select语句中的变量使我吃饱了。 Assuming the db column names can be used as variable names, I want something like this: 假设数据库列名称可以用作变量名称,我想要这样的东西:
for id, name, area in db.select(from='sometable', where='area IS NOT NULL'):
print id, name, area
Of course the variables in the for statement must be dynamically passed into db.select
, so that I can change it without changing db.select
. 当然,必须将for语句中的变量动态地传递到
db.select
,以便我可以更改它而无需更改db.select
。
The one solution in the comment, suggesting to use a dictionary row factory, seems very close to what you want. 评论中的一个解决方案,建议使用字典行工厂,似乎与您想要的非常接近。
Even closer (as easier to write) seems to me a namedtuple
. 在我看来,更接近(更容易写)的是一个
namedtuple
。 For this purpose, I once wrote this: 为此,我曾经这样写过:
def namtupiter(c):
from collections import namedtuple
fields = tuple(i[0] for i in c.description)
Row = namedtuple('Row', fields)
# make Row a tuple and a "dict" (well, kind of...) at the same time.
# Don't lose tuple property, so only process strings and pass everything
# other to super().
Row.__getitem__ = lambda self, item: getattr(self, item) if isinstance(item, basestring) else super(Row, self).__getitem__(item)
for i in c:
try:
# try to access i as a dict
yield Row(*(i[f] for f in fields))
except TypeError:
# it is no dict -> try tuple
yield Row(*i)
class CursorNTRowsMixIn(object):
_fetch_type = 0 # tuples
def _do_get_result(self):
super(CursorNTRowsMixIn, self)._do_get_result()
# create a named tuple class
from collections import namedtuple
if self.description:
self.RowClass = namedtuple('Row', tuple(i[0] for i in self.description))
def _fetch_row(self, size=1):
rows = super(CursorNTRowsMixIn, self)._fetch_row(size)
# turn every row into a Row().
return tuple(self.RowClass(*i) for i in rows)
class NTCursor(CursorStoreResultMixIn, CursorNTRowsMixIn,
BaseCursor):
pass
class SSNTCursor(CursorUseResultMixIn, CursorNTRowsMixIn,
BaseCursor):
pass
With the namtupiter()
, you can iterate over a cursor containing a resultset and receive NamedTuples with the DB fields contained as attributes. 使用
namtupiter()
,您可以遍历包含结果集的游标,并接收包含DB域作为属性的NamedTuples。
So you can do 所以你可以做
for r in namtupiter(db.select(fields=('id', 'name', 'area', _from='sometable', where='area IS NOT NULL')):
print r.id, r.name, r.area
Another way is the ( SS
) NTCursor
which can be seen as an alternative to the existing cursors which provide tuples or dicts. 另一种方法是(
SS
) NTCursor
,可以将其视为提供元组或字典的现有游标的替代方法。 These new cursors as well provide the rows as named tuples with the name information extracted from the result set. 这些新的游标还为命名为元组的行提供从结果集中提取的名称信息。
The following example is not using namedtuple. 以下示例未使用namedtuple。 I'm using mysql.connector, but can be done with whatever database driver:
我正在使用mysql.connector,但是可以使用任何数据库驱动程序来完成:
import mysql.connector
CONFIG = {
'database': 'test',
'user': 'root',
}
class MySQLStackOverflowConnect(mysql.connector.MySQLConnection):
def select(self, table, where, fields=None):
if isinstance(fields, (list, tuple)):
select_fields = ', '.join(fields)
else:
select_fields = '*'
query = "SELECT {fields} FROM `{table}` WHERE {where}".format(
table=table, where=where, fields=select_fields)
cur = self.cursor(buffered=True)
cur.execute(query)
return cur
cnx = MySQLStackOverflowConnect(**CONFIG)
for userid, username in cnx.select(table='users', where='id=1',
fields=('id', 'username')):
print userid, username
cnx.close()
(Careful for SQL-injection with passing WHERE-clauses like that) (通过这样的WHERE子句小心SQL注入)
With Python 3, you would be able to do the last for-loop, provided the table has id
and username
as first fields, like this: 使用Python 3,您可以执行最后一个for循环,前提是该表具有
id
和username
作为第一个字段,例如:
for userid, username, *rest in cnx.select(table='auth_user', where='id=1'):
print(userid, username)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.