nghs nghs - 3 years ago 174
Python Question

Importing in Python for multiple files

I am struggling to figure out how to handle importing dependencies that are used in multiple files.

Let's say I want to import an external API for example, and two classes depend on this import. Putting the import into the 'index' file, as an attempt to make it global does not work. I can import it in each class file fine, but that seems to be a violation of DRY, as well as setting myself up for failure later on.

So is there a way to import once, in a single file that is globally accessible? What I experimented with was creating an

index.py
,
foo.py
(for the foo class) and
bar.py
(for the bar class):

Index:

from example import API
import foo
import bar

foo()
bar()


foo.py:

class foo:
... (try to put the example API to use)


bar.py: (same as
foo.py
really, just here to make the case for using the same dependency in two different places)

This failed to work, as the classes appeared to not be able to access
exampleAPI
. What is the correct way to do this, or am I looking at it wrong? Thanks!

Answer Source

In general, you should import each module you need in each of your own modules that needs to use it. You don't need to worry about duplication, since each module has its own global namespace. Furthermore, modules are cached (in the sys.modules dictionary) so you don't need to worry about extra work being done to load the module multiple times.

That said, there can be some exceptions. For instance, if the specific source of an API is considered "private" information (e.g. because it's an implementation detail or because it might be configurable and not always come from the same place all the time), it might make sense to import it into some namespace where all other users will look for it.

On the other hand, your example suggests you may be splitting up your code more than you should. Unlike some other languages (such as Java), in Python it's neither required nor recommended for each class to live in its own file. Instead, you should divide your code up into modules dictated by how closely they interact with each other. Closely related classes should be part of the same module, while pieces that don't interact at all might make more sense in separate modules (especially if some other code might need one part but not the other). It may not be inappropriate for your whole program to be in a single module! Obviously, some of this is a matter of style and taste, so there's not a single best option for every programmer in every situation.

For your example code, if you want to keep separate modules, I'd suggest something like this:

index.py:

from foo import Foo # no need to import API here if you're not using it directly
from bar import Bar

foo = Foo() # create an instance of the foo class
result = foo.some_method() # call methods on it
bar = Bar(foo) # you can also pass your instances around to other classes

foo.py:

from example import API

class Foo:
    def some_method(self):
        return API.whatever() # use the API in some way

bar.py:

from example import API # don't worry about importing the API more than ocne

class Bar:
    def __init__(self, foo):
        self.foo = foo

    def blah(self):
        API.something_else(self.foo.some_method())

Note that I changed some names around. Python's convention is to use CapitalizedNames for classes, and lowercase_names_with_underscores (sometimes known as "snake case") for modules, variables and methods. Your original code seemed to have some confusion between the modules name foo and bar and the classes within them with the same names. Using different styles for the different names can help avoiding that confusion.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download