从仅影响一类的内建函数导入对象

时间:2018-08-29 13:33:53

标签: python python-3.x python-2.7 future new-style-class

我正在使用newstylefuture类的代码从python2转换为python3。我的项目在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后调用此Form时,失败,并出现以下错误:

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文件中的一个类,而不会影响其他类。还是有其他方法可以解决这个问题?

3 个答案:

答案 0 :(得分:4)

您遇到的问题似乎来自两个不同的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

并从具有此__unicode__方法的newobject继承

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中的那个?

答案 1 :(得分:0)

这是python2方式。

"MyPrivateLibrary.podspec passed validation"

在python3类中,对象隐式继承了对象,因此应该像这样;

class Address(object):

答案 2 :(得分:0)

今天就讨论这个问题,Patrick Haugh主要描述了问题,除了在Django 1.11(问题中的版本以及我正在使用的版本)中未引用sixpython_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管理员具有日志记录功能,可创建包含以下内容的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. django数据库模型的
  6. __str__被实现为django https://github.com/django/django/blob/stable/1.11.x/django/db/models/base.py#L595
  7. unicode 的包装

我们没有很好的解决方案,除了如果我们需要同时将Future导入为from builtins import object as future_object之外,还可以通过运行futurize --stage2 -x object而不是futurize --stage2来禁用整个修订,< / p>