2

I'm quite new at Python, but I'm experienced with other programming languages.

I have this line of code:

import module as m

If I try to access its functions:

m.spam.foo()
m.eggs.bar()

I get the following errors:

AttributeError: module 'module' has no attribute 'spam'
AttributeError: module 'module' has no attribute 'eggs'

On the other hand, if I write:

import module.spam, module.eggs

and then:

module.spam.foo()
module.eggs.bar()

It works properly.


Same if I write:

from module import spam, eggs

and:

spam.foo()
eggs.bar()

Works with no errors.


I prefer the first method since I don't have to manually import every single submodule before using it...

So, what's wrong with that method? Is there a workaround to make it work (I do not like the from module import * approach since they can be confused with my global variables)?

I searched everywhere inside the reference but could not find anything.

Simo Pelle
  • 141
  • 1
  • 11
  • Importing all the modules at the beginning is the recommended technique in [PEP 8 - Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) — there are exceptions to the rule, of course. – martineau Dec 05 '20 at 02:02
  • Thanks... I didn't know about it! Anyway, it doesn't solve the fact that I have to manually import every single submodule – Simo Pelle Dec 05 '20 at 07:54
  • If your question is about submodules in a Python package, you can `import` things from the submodules in the package's `__init__.py` file. Normally this will require explicitly importing everything. There are however ways of doing that automatically (and I've answered other questions showed how to do it if you're interested). – martineau Dec 05 '20 at 19:21
  • @martineau is this file `__init__.py` automatically included in every third party libraries or should I create it manually? – Simo Pelle Dec 06 '20 at 21:55
  • Packages come with one because it's a big part of what makes them a package. I think you should look up "package" in the documentation (or some other Python resource). Also see my answer to [How to import members of all modules within a package?](https://stackoverflow.com/questions/14426574/how-to-import-members-of-all-modules-within-a-package) – martineau Dec 06 '20 at 23:01
  • @martineau Importing `module.__init__` I still get the error `AttributeError: module 'module' has no attribute 'spam'`... I cannot understand whether I'm doing something wrong, since `module.__init__` is actually imported with no errors. – Simo Pelle Dec 07 '20 at 02:15
  • You still don't understand how packages work — the `__init__.py` is imported automatically when you import the package or one of the submodules in it. – martineau Dec 07 '20 at 06:30
  • @martineau so the submodules should automatically be imported... Why do I get these errors? – Simo Pelle Dec 08 '20 at 14:25
  • No, submodules will not be automatically imported. The `__init__.py` is what tells Python that the folder it is in is a package. You can manually `import` stuff from the sub-modules in the `__init__.py` and they will be appear to be in _its_ name namespace instead of the submodule's. There are ways to make this importing of submodules happen automatically (by adding some code that looks for submodules a imports whatever is in them into the packages namespace). Afterwards, If you want everything, you can just do `from package import *`. – martineau Dec 08 '20 at 15:11
  • @martineau thank you... one last question. What if I want to import all the submodules and keep them inside the parent module? The problem with `from package import *` is that the submodules are saved inside their own namespaces. I'd like to access them from the main module (`module.egg.foo()` instead of `egg.foo()`) – Simo Pelle Dec 08 '20 at 15:25
  • Hard to tell from your example, but if you had an empty `__init__.py`, then you could `import` a module in the package via `from package import module`. Afterwards `module.egg.foo()` would be valid (assuming something named `egg` with a callable `foo` is defined in it. – martineau Dec 08 '20 at 16:28

1 Answers1

0

I don't know how well this solves your problem, because this code is actually longer than the from module import spam, eggs method, but this question might solve your problem. Basically, you would use an __init__ function to load all submodules.

AgentLoneStar007
  • 117
  • 3
  • 12
  • It doesn't, since my module is a third party library (`matplotlib`) so I think that editing it is not a good idea... – Simo Pelle Dec 05 '20 at 07:52
  • Sorry. Best I had. – AgentLoneStar007 Dec 05 '20 at 17:04
  • @Foxel: If the third party package doesn't supply and `__iinit__.py`, you shouldn't try creating one. You could create your own **module** and import a bunch of things from other modules & packages into **it**, and then use `from my_module import *` and access to all of them. You can also explicitly state what should be included by `… import *` by defining a list named `__all__` with their names in it in the module's code. – martineau Dec 06 '20 at 23:19
  • @martineau I tried importing it and the file actually exists, the problem is that I still get the same errors – Simo Pelle Dec 07 '20 at 02:17