如何从仅影响一个类的内置导入对象?



我正在使用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.

  1. NewObject(来自内置导入对象(添加了一个名为统一码: https://github.com/PythonCharmers/python-future/blob/master/src/future/types/newobject.py#L41
  2. django 管理员有一个日志记录功能创建一个包含 对象的文本表示形式。https://github.com/django/django/blob/stable/1.11.x/django/contrib/admin/options.py#L741
  3. 使用的文本表示形式为object.__unicode__: https://github.com/django/django/blob/stable/1.11.x/django/utils/encoding.py#L77
  4. __unicode__是未来包中__str__的包装器
  5. 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来禁用整个修复

程序

最新更新