连接MySQL过程中,
with con:
cur = con.cursor()
cur.executemany(final_str, symbols)
出现如下错误:
关乎with语句的用法中上下文管理器。
上下文管理器必须同时提供 __enter__()
和 __exit__()
方法的定义,缺少任何一个都会导致 AttributeError;with 语句会先检查是否提供了 __exit__()
方法,然后检查是否定义了 __enter__()
方法。
AttributeError指的是属性错误,就是说con这个对象没有__enter__
属性,不能用在with语句中,确切的说是不能用于 context managers(上下文管理器)。
With 语句仅能工作于支持上下文管理协议(context management protocol)的对象。也就是说只有内建了”上下文管理”的对象才能和 with 一起工作。Python内置了一些支持该协议的对象,如下所列是一个简短列表:
-
file
-
decimal.Context
-
thread.LockType
-
threading.Lock
-
threading.RLock
-
threading.Condition
-
threading.Semaphore
-
threading.BoundedSemaphore
-
with connect
-
原因解释
MySQLdb/connections.py以前是有上下文协议的,2018.12.4去掉了。
Remove context interface from Connector (#295)
def __enter__(self):
from warnings import warn
warn("context interface will be changed. Use explicit conn.commit() or conn.rollback().",
DeprecationWarning, 2)
if self.get_autocommit():
self.query("BEGIN")
return self.cursor()
def __exit__(self, exc, value, tb):
if exc:
self.rollback()
else:
self.commit()
自己写一个上下文对象:
import MySQLdb as mdb
import MySQLdb.cursors as mc
import contextlib
DictCursor = mc.DictCursor
SSCursor = mc.SSCursor
SSDictCursor = mc.SSDictCursor
Cursor = mc.Cursor
@contextlib.contextmanager
def connection(cursorclass=Cursor,
host='localhost', user='root',
passwd='---', dbname='---',
driver=mdb):
connection = driver.connect(
host=host, user=user, passwd=passwd, db=dbname,
cursorclass=cursorclass)
try:
yield connection
except Exception:
connection.rollback()
raise
else:
connection.commit()
finally:
connection.close()