我正在使用future
将代码从 python2 转换为 python3 以用于newstyle
类。我的项目在 Django 1.11 中
我有一个 forms.py 课,如下:
class Address:
...rest of code...
class AddressForm(Address, forms.ModelForm):
...rest of code...
在 Python 2 中
转换为:
from buitlins import object
class Address(object):
...rest of code...
class AddressForm(Address, forms.ModelForm):
...rest of code...
在 Python 3 中
我有一个硒测试,在转换为 Python3 后调用此表单时失败,并出现以下错误:
File "<path_to_venv>/local/lib/python2.7/site-packages/django/utils/six.py", line 842, in <lambda>
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
File "<path_to_venv>/local/lib/python2.7/site-packages/future/types/newobject.py", line 78, in __unicode__
s = type(self).__str__(self)
RuntimeError: maximum recursion depth exceeded
但是,当我删除导入from buitlins import object
测试通过时。
但是当我添加了一个未来的检查时,我得到了一个未来的差异错误,因此每个类都必须转换为 newstyle。我希望它同时适用于Python2和Python3。
有没有办法这个模块builtins
模块导入只能影响forms.py
文件中的一个类,而不会影响其他类。还是有其他方法可以解决这个问题?
你遇到的问题似乎来自两个不同的Python 2现代化工具的战斗。您似乎正在使用django.utils.six
中的python_2_unicode_compatible
装饰器
def python_2_unicode_compatible(klass):
"""
A decorator that defines __unicode__ and __str__ methods under Python 2.
Under Python 3 it does nothing.
To support Python 2 and 3 with a single code base, define a __str__ method
returning text and apply this decorator to the class.
"""
if PY2:
if '__str__' not in klass.__dict__:
raise ValueError("@python_2_unicode_compatible cannot be applied "
"to %s because it doesn't define __str__()." %
klass.__name__)
klass.__unicode__ = klass.__str__
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
return klass
并从newobject
继承,具有此__unicode__
方法
def __unicode__(self):
# All subclasses of the builtin object should have __str__ defined.
# Note that old-style classes do not have __str__ defined.
if hasattr(self, '__str__'):
s = type(self).__str__(self)
else:
s = str(self)
if isinstance(s, unicode):
return s
else:
return s.decode('utf-8')
而且由于两者在提供__unicode__
和__str__
方法的策略略有不同,因此它们无限地相互调用,这会导致您的递归错误。
提供 builtins.object 的模块提供了自己的python_2_unicode_compatible
装饰器。您是否尝试过使用它而不是django.utils.six
?
这是 python2 的方式。
class Address(object):
在 python3 中,类隐式继承对象,所以它应该是这样的;
class Address:
今天遇到了这个问题,Patrick Haugh 主要描述了这个问题,除了 django 1.11 中没有引用 6 和python_2_unicode_compatible
,问题中的版本和我正在使用的版本。 在我们的例子中,问题在于 django 模型继承自 mixin,该 mixin 继承自future.builtins.newobject
.
- NewObject(来自内置导入对象(添加了一个名为统一码: https://github.com/PythonCharmers/python-future/blob/master/src/future/types/newobject.py#L41
- django 管理员有一个日志记录功能创建一个包含 对象的文本表示形式。https://github.com/django/django/blob/stable/1.11.x/django/contrib/admin/options.py#L741
- 使用的文本表示形式为
object.__unicode__
: https://github.com/django/django/blob/stable/1.11.x/django/utils/encoding.py#L77 __unicode__
是未来包中__str__
的包装器- Django 数据库模型的
__str__
在 Django https://github.com/django/django/blob/stable/1.11.x/django/db/models/base.py#L595 中作为Unicode的包装器实现
。
我们没有一个很好的解决方案,除了在我们需要访问两者时显式导入 futurefrom builtins import object as future_object
,并通过运行futurize --stage2 -x object
而不是futurize --stage2
来禁用整个修复