58

abc.ABCMetaをメタクラスとして持ち、Python 2.7 と Python 3.5 の両方と互換性のあるクラスを作成したいと考えています。これまで、2.7 または 3.5 でのみ成功しましたが、両方のバージョンで同時に成功したことはありません。誰か手を貸してくれませんか?

Python 2.7:

import abc
class SomeAbstractClass(object):
    __metaclass__ = abc.ABCMeta
    @abc.abstractmethod
    def do_something(self):
        pass

パイソン 3.5:

import abc
class SomeAbstractClass(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def do_something(self):
        pass

テスト

適切なバージョンの Python インタープリター (Python 2.7 -> 例 1、Python 3.5 -> 例 2) を使用して次のテストを実行すると、両方のシナリオで成功します。

import unittest
class SomeAbstractClassTestCase(unittest.TestCase):
    def test_do_something_raises_exception(self):
        with self.assertRaises(TypeError) as error:
            processor = SomeAbstractClass()
        msg = str(error.exception)
        expected_msg = "Can't instantiate abstract class SomeAbstractClass with abstract methods do_something"
        self.assertEqual(msg, expected_msg)

問題

Python 3.5 を使用してテストを実行している間、期待される動作は発生しません (TypeErrorインスタンス化中に は発生しませんSomeAbstractClass)。

======================================================================
FAIL: test_do_something_raises_exception (__main__.SomeAbstractClassTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tati/sample_abc.py", line 22, in test_do_something_raises_exception
    processor = SomeAbstractClass()
AssertionError: TypeError not raised

----------------------------------------------------------------------

一方、Python 2.7 を使用してテストを実行すると、次のエラーが発生しSyntaxErrorます。

 Python 2.7 incompatible
 Raises exception:
  File "/home/tati/sample_abc.py", line 24
    class SomeAbstractClass(metaclass=abc.ABCMeta):
                                     ^
 SyntaxError: invalid syntax
4

4 に答える 4

5

を使用する場合は、Python 2 で明示的に渡す必要がありstr('ABC')ます。abc.ABCMetafrom __future__ import unicode_literals

それ以外の場合、Python は を発生させTypeError: type() argument 1 must be string, not unicodeます。

以下の修正されたコードを参照してください。

import sys
import abc
from __future__ import unicode_literals

if sys.version_info >= (3, 4):
    ABC = abc.ABC
else:
    ABC = abc.ABCMeta(str('ABC'), (), {})

これには別の回答は必要ありませんが、残念ながらあなたの回答にコメントすることはできません(担当者がさらに必要です)。

于 2017-06-19T08:53:44.840 に答える