7

我正在将代码从 python2 转换为 python3 用于newstyle使用future. 我的项目在 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 中

我有一个 selenium 测试,它在转换为 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文件中的其他类。还是有其他方法可以解决这个问题?

4

3 回答 3

6

您遇到的问题似乎来自两个不同的 Python 2 现代化工具的冲突。您似乎正在使用来自的python_2_unicode_compatible装饰器django.utils.six

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装饰器。您是否尝试过使用它而不是 from django.utils.six

于 2018-08-29T14:10:19.573 回答
0

这是python2的方式。

class Address(object):

在python3类中隐式继承对象,所以应该是这样的;

class Address:
于 2018-08-29T13:40:05.270 回答
0

今天遇到这个问题,Patrick Haugh 主要描述了这个问题,除了django 1.11 中没有引用的六个python_2_unicode_compatible问题中的版本和我正在使用的版本。在我们的例子中,问题在于 django 模型继承自 mixin,而 mixin 继承自future.builtins.newobject.

  1. newobject(来自内置导入对象)添加了一个名为 unicode的属性:https ://github.com/PythonCharmers/python-future/blob/master/src/future/types/newobject.py#L41
  2. django admin 具有日志记录功能,可创建包含对象文本表示的 LogEntry。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. __str__对于 django db 模型在 django https://github.com/django/django/blob/stable/1.11.x/django/db/models/base.py#L595中实现为unicode的包装器

我们没有一个很好的解决方案,除了显式导入未来,from builtins import object as future_object好像我们需要访问两者,并通过运行futurize --stage2 -x object而不是禁用整个修复futurize --stage2

于 2020-08-15T01:29:31.093 回答