Как импортировать модуль из каталога на уровне выше текущего script

Для моего приложения Python у меня есть следующая структура каталогов:

\myapp
\myapp\utils\
\myapp\utils\GChartWrapper\
\myapp\model\
\myapp\view\
\myapp\controller\

Один из моих классов в\myapp\view\должен импортировать класс GChartWrapper. Тем не менее, я получаю ошибку импорта...

myview.py
from myapp.utils.GChartWrapper import *

Вот ошибка:

<type 'exceptions.ImportError'>: No module named GChartWrapper.GChart
      args = ('No module named GChartWrapper.GChart',)
      message = 'No module named GChartWrapper.GChart' 

Что я делаю неправильно? Мне действительно тяжело импортировать модули/классы в Python...

Ответ 1

__init__.py file пакета GChartWrapper ожидает пакет GChartWrapper на PYTHONPATH. Вы можете сказать по первой строке:

from GChartWrapper.GChart import *

Нужно ли включать пакет GChartWrapper в структуру каталога вашего пакета? Если это так, то одна вещь, которую вы можете сделать, это добавить путь, по которому пакет находится в sys.path во время выполнения. Я полагаю, что myview.py находится в каталоге myapp\view? Затем вы можете сделать это, прежде чем импортировать GChartWrapper:

import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'utils')))

Если нет необходимости иметь его в структуре каталогов, его проще было бы установить в обычном месте. Вы можете сделать это, запустив setup.py script, который включен в дистрибутив GChartWrapper.

Ответ 2

Вы не импортируете модули и пакеты из двоичных путей. Вместо этого в python вы используете пакеты и абсолютный импорт. Это позволит избежать всех будущих проблем.

Пример:

создайте следующие файлы:

MyApp\myapp\__init__.py
MyApp\myapp\utils\__init__.py
MyApp\myapp\utils\charts.py
MyApp\myapp\model\__init__.py
MyApp\myapp\view\__init__.py
MyApp\myapp\controller\__init__.py
MyApp\run.py
MyApp\setup.py
MyApp\README

Файлы должны быть пустыми, за исключением следующих:

MyApp\myapp\utils\charts.py:

class GChartWrapper(object):
    def __init__(self):
        print "DEBUG: An instance of GChartWrapper is being created!"

MyApp\myapp\view\__init__.py:

from myapp.utils.charts import GChartWrapper

def start():
    c = GChartWrapper() # creating instance of the class

MyApp\run.py:

from myapp.view import start
start()

Это все! Когда вы запустите свою точку входа (run.py), она вызывает функцию в представлении и создает экземпляр класса GChartWrapper. Используя эту структуру, вы можете импортировать что угодно и использовать ее.

В дополнение к MyApp\setup.py вы пишете программу установки для пакета MyApp\myapp. Используйте distutils, чтобы записать его:

from distutils.core import setup
setup(name='MyApp',
      version='1.0',
      description='My Beautiful Application',
      author='Martin',
      author_email='[email protected]',
      url='http://stackoverflow.com/questions/1003843/',
      packages=['myapp'],
      scripts=['run.py']
     )

Этого достаточно. Теперь, когда люди загружают папку MyApp, они могут просто установить ее с помощью setup.py и запустить ее с помощью run.py. Distutils может создавать пакеты в нескольких форматах, включая устанавливаемые Windows.EXE

Это стандартный способ распространения пакетов/приложений python.

Ответ 3

Вы можете изменить путь, в котором python ищет файлы.

В верхней части исходного файла добавьте:

import sys
sys.path.append("..") 

Или, альтернативно, измените переменную среды:

export PYTHONPATH=..

Ответ 5

GChartWrapper также доступен из PyPI, поэтому вы можете использовать easy_install или pip для установки модуля:

sudo pip install GChartWrapper==0.9

Затем он будет автоматически добавлен в ваш PYTHONPATH, а затем вы можете удалить его из каталога /myapp/utils. Если вы не можете использовать sudo, посмотрите на использование virtualenv (и virtualenvwrapper).