2 ms·
Woah, we don't need __init__.py any more. Mind blown.
by foobarbecue 4y ago
Woah, we don't need __init__.py any more. Mind blown.
- nerdponx 4y agoYou still do. These "init-less" packages are something specific called namespace packages, and you shouldn't use them unless you have a good reason to use them. See https://www.python.org/dev/peps/pep-0420/ https://www.python.org/dev/peps/pep-0420/.
- foobarbecue 4y agoAh, thanks, I was jumping to conclusions.
- nerdponx 4y agoIt's not your fault, the article also didn't explain it, and it makes me think that the article author didn't understand it either.
- zx14 4y agoCan you please explain why not use them or what's the use case?
- nerdponx 4y agoThe difference is that namespace packages can exist in more than one place at a time, while regular packages cannot. Python looks for regular packages (which are really just modules that can contain other modules) by searching a pre-defined list of directories, stopping at the first valid entry. What happens when you run `import foobar`? Let's say that the search path is: sys.path = [ # The current working directory '', # System package locations '/usr/lib/python3.9/site-packages', '/usr/local/lib/python3.9/site-packages', ] And let's say that you have these files on your system: /usr/lib/python3.9/ └── foobar/ ├── __init__.py └── nice.py /usr/local/lib/python3.9/ └── foobar/ ├── __init__.py └── wow.py In this situation, Python finds the version in /usr/lib/ because that directory comes first in the search path, and ignores the other one entirely. You can do `import foobar` or `import foobar.nice` or `from foobar import nice`, but you can't do `import foobar.wow` or `from foobar import wow`. Now let's assume that you didn't have the `__init__.py` files: /usr/lib/python3.9/site-packages/ └── foobar/ └── nice.py /usr/local/lib/python3.9/site-packages/ └── foobar/ └── wow.py From the perspective of the Python import system, `foobar` is no longer a regular package but a namespace package. You will be able to `import foobar`, but you will not be able to access anything inside it! However, you will be able to do both `import foobar.nice` (or `from foobar import nice`) and `import foobar.wow` (or `from foobar import wow`) and be able to access both modules freely that way. That is, `foobar` as a namespace package is no longer useful by itself, but now it acts as a namespace for several other packages that might live in different locations on your system. The use case for this feature is the ability to split a package over several distributions. For example, you can install one or both of zope.interface and zope.component, and they will both be available to import from the "zope." namespace. It is also useful within organizations, where you can namespace all of your internally-developed libraries with some identifier specific to your organization. You could even emulate a reverse-domain namespacing system this way if you wanted to: /usr/local/lib/python3.9/site-packages/ └── org/ └── best_stuff/ └── pytools/ ├── thing1.py └── thing2.py Which you could import as, e.g. `from org.best_stuff.pytools import thing1, thing2`. As you might imagine, spreading a package across multiple locations is not a desirable outcome if you aren't expecting it. So you shouldn't use namespace packages unless you specifically want the behavior I described above.
- zx14 4y agoWhat a legend. Thank you very much.