Загружать разные модули без изменения логического файла

Предположим, у меня есть 2 разных модуля с одинаковыми (одинаковыми) интерфейсами. Список файлов выглядит так:

root/
   logic.py
   sns_api/
      __init__.py
      facebook/
          pyfacebook.py
          __init__.py
      myspace/
          pymyspace.py
          __init__.py

И pyfacebook.py и pymyspace.py имеют одинаковые интерфейсы, что означает:

# in pyfacebook.py
class Facebook:
   def __init__(self, a, b):
       # do the init
   def method1(self, a, b, ...):
       # do the logic

# in pymyspace.py
class Myspace:
   def __init__(self, a, b):
       # do the init
   def method1(self, a, b, ...):
       # do the logic

Теперь у меня есть вопрос. Я хочу сделать логику в logic.py без дублирования кодов, поэтому мне интересно, как я могу просто установить флаг, чтобы показать, какой модуль я использую, и python автоматически загрузит нужные коды, что означает:

# in logic.py

PLATFORM = "facebook"

# import the right modules in, complete the logic with the current platform
# create the right instance and invoke the right methods

Затем я изменяю PLATFORM = 'myspace', логика будет работать автоматически.

Так как я могу это сделать?

Мне интересно, будет ли работать динамический импорт, или eval raw python-коды, но, похоже, не очень хорошее решение. Или если я могу сделать единую обертку в

sns_api/__init__.py

Кто-нибудь может помочь?

3 ответа

Решение

С двумя я бы сделал

if platform == 'facebook':
    from pyfacebook import FaceBook as Platform
elif platform == 'myspace':
    from pymyspace import Myspace as Platform
else:
    raise RuntimeError, "not a valid platform"

и использовать Platform в остальной части кода. Это сделано так в библиотеке, см. os модуль.

Вы можете сделать действительно динамический импорт, используя name =__import__('module'), но вам, вероятно, это не нужно.

Имейте функцию "фабрики" в каждом модуле, делайте динамический импорт и вызывайте фабрику для загруженного модуля. По крайней мере, это один из способов сделать это. Помните, что питонский способ - это "типизирование утки", поэтому фабрика возвращает объект, а клиент использует его через "утиные вызовы":-)

Вы также можете использовать exec:

exec "from sns_api.%s import Platform" % PLATFORM

Затем в ваших файлах реализации назначьте что-то платформе:

# in pyfacebook.py
class Facebook:
   def __init__(self, a, b):
       # do the init
   def method1(self, a, b, ...):
       # do the logic

Platform = Facebook
Другие вопросы по тегам