iTayb
iTayb

Reputation: 12753

Accessing shared modules from child packages

I'm having difficulties with using internal imports inside my projects. This is a partial tree structure of my project:

app
  |- Gui.py
  |- Main.py
  |- logger.py
  |- config.py
  |- WebParser (package)
        |- __init__.py
        |- LinksGrabber.py
        |- LyricsGrabber.py
        |- ImagesGrabber.py
  |- (Many other packages...)

the logger.py and config.py modules are required in every package's modules, and are independent (uses only bulit-in modules). It is tricky to access these modules from inside packages.

This is how I tried to achieve it, for enabling configuration access and logging feature in WebParser\LinksGrabber.py:

# WebParser\__init__.py:
sys.path.append('..') # for outside-package modules
import config
from logger import log

# WebParser\LinksGrabber.py:
import WebParser
config = WebParser.config
log = WebParser.log

The Problems:

Can you suggest a better implemention, or a different code design?

Upvotes: 1

Views: 155

Answers (3)

BrenBarn
BrenBarn

Reputation: 251538

You should make app a package by giving it an __init__.py file. The python relative import system only works inside packages. Then inside your WebParser modules, you can do from .. import config, from .. import Gui, etc.

As for importing WebPackage from the packages inside it, that is a bit of a code smell. Why do you need to do that? Using relative imports you could instead, for instance, have from . import LinksGrabber inside ImagesGrabber, etc., to access what you need. If there are functions that are part of the WebParser package that are needed by many of the submodules, you should pull those out into a separate module in WebParser.

Upvotes: 1

jdeuce
jdeuce

Reputation: 1866

I would make the entire outer (app) directory a python package (with an __ init__.py).

app_files
  |- ***setup.py***
  |- app
    |- ***__init__.py***
    |- Gui.py
    |- Main.py
    |- logger.py
    |- config.py
    |- WebParser (package)
          |- __init__.py
          |- LinksGrabber.py
          |- LyricsGrabber.py
          |- ImagesGrabber.py
    |- (Many other packages...)

setup.py would be something simple like this:

#!/usr/bin/env python

from distutils.core import setup

setup(name='app',
      version='1.0',
      description='My app',
      author='Greg Ward',
      packages=['app'],
     )

then you can run python setup.py install, to permanently install 'app' into the python path. This is, in my opinion, the best way to do it without resorting to sys.path hacks everywhere.

Then, from anywhere in python you can refer to any of your files from the full dotted paths

i.e.

import app.logger
import app.config
import app.WebParser

The only way to make LinksGrabber and LyricsGrabber available from just an import app.WebParser would be to import them from app.WebParser.__ init__.

Upvotes: 1

mgilson
mgilson

Reputation: 310097

It seems that you could use relative imports here:

from .. import config
from ..logger import log

Upvotes: 0

Related Questions