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
from example import API
... (try to put the example API to use)
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:
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
from example import API class Foo: def some_method(self): return API.whatever() # use the API in some way
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
bar and the classes within them with the same names. Using different styles for the different names can help avoiding that confusion.