Question

For my Python application, I have the following directories structure:

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

One of my class in \myapp\view\ must import a class called GChartWrapper. However, I am getting an import error...

myview.py
from myapp.utils.GChartWrapper import *

Here is the error:

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

What am I doing wrong? I really have a hard time to import modules/classes in Python...

Was it helpful?

Solution

The __init__.py file of the GChartWrapper package expects the GChartWrapper package on PYTHONPATH. You can tell by the first line:

from GChartWrapper.GChart import *

Is it necessary to have the GChartWrapper included package in your package directory structure? If so, then one thing you could do is adding the path where the package resides to sys.path at run time. I take it myview.py is in the myapp\view directory? Then you could do this before importing GChartWrapper:

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

If it is not necessary to have it in your directory structure, it could be easier to have it installed at the conventional location. You can do that by running the setup.py script that's included in the GChartWrapper source distribution.

OTHER TIPS

You don't import modules and packages from arbritary paths. Instead, in python you use packages and absolute imports. That'll avoid all future problems.

Example:

create the following files:

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

The files should be empty except for those:

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()

That's all! When you run your entry point (run.py) it calls a function on the view, and that creates an instance of the GChartWrapper class. Using this structure you can import anything anywhere and use it.

To complement, in MyApp\setup.py you write an installation program for the MyApp\myapp package. Use distutils to write it:

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

That is enough. Now when people download the MyApp folder, they can just install it using setup.py and run it using run.py. Distutils can generate packages in a number of formats including windows installable .EXE

It's the standard way of distributing python packages/applications.

You can change the path where python looks for files.

At the top of your source file, add:

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

Or alternatively change the environment variable:

export PYTHONPATH=..

Or starting in python 2.5 (again assuming myview is in myapp\view:

from __future__ import absolute_import
from ..utils.GChartWrapper import *

See: http://docs.python.org/whatsnew/2.5.html#pep-328-absolute-and-relative-imports

GChartWrapper is also available from PyPI so you can use easy_install or pip to install the module:

sudo pip install GChartWrapper==0.9

It will then be automatically added to your PYTHONPATH and then you can remove it from your /myapp/utils directory. If you can't use sudo, look at using virtualenv (and virtualenvwrapper).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top