Я использую декларативное расширение в SQLAlchemy, и я заметил странную ошибку, когда попытался сохранить экземпляр сопоставленного класса с неверными данными (в частности, столбец, объявленный с nullable = False со значением None).
Класс (упрощенный):
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, autoincrement=True)
userid = Column(String(50), unique=True, nullable=False)
Причинение ошибки (сеанс является сеансом SQLAlchemy):
>>> u = User()
>>> session.add(u)
>>> session.commit()
...
TypeError: exceptions must be old-style classes or derived from BaseException, not NoneType
Глядя на код, который вызывает это исключение, я обнаружил (в sqlalchemy.orm.session):
except:
transaction.rollback(_capture_exception=True)
raise
Исключением, которое перехватывается в этом случае, является sqlalchemy.exc.OperationalError. Если я изменю эти строки на:
except Exception as e:
transaction.rollback(_capture_exception=True)
raise e
затем проблема исчезает, и вместо None выдается ошибка OperationalError. Не должен ли оригинальный код работать в любой недавней версии Python? (Я использую 2.7.2) Эта ошибка как-то специфична для моего приложения?
Python 2.7.2
SQLAlchemy 0.7.5
ОБНОВЛЕНИЕ: похоже, ошибка в некоторой степени относится к моему приложению. Я обертываю файл eventlet.db_pool движком SQLAlchemy, который как-то является источником проблемы. Запуск моего простого теста с использованием SQLite в памяти или базового движка MySQL не имеет этой проблемы, но с db_pool это имеет место.
Контрольный пример: https://gist.github.com/1980584
Полный возврат:
Traceback (most recent call last):
File "test_case_9525220.py", line 41, in <module>
session.commit()
File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 645, in commit
self.transaction.commit()
File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 313, in commit
self._prepare_impl()
File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 297, in _prepare_impl
self.session.flush()
File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1547, in flush
self._flush(objects)
File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1635, in _flush
raise
TypeError: exceptions must be old-style classes or derived from BaseException, not NoneType