I'm brand new at python package management, and surely have done something wrong. I was encouraged to create a directory structure as follows:
bagoftricks ├── bagoftricks │ ├── bagoftricks │ │ ├── __init__.py │ │ └── bagoftricks.py │ └── __init__.py ├── README.md └── setup.py
bagoftricks.py contains two functions, levenshtein()
and geofind()
.
I would like to call these as:
import bagoftricks x = bagoftricks.levenshtein(arg1,arg2)
Instead, I find I have to do this:
import bagoftricks x = bagoftricks.bagoftricks.levenshtein(arg1,arg2)
Is there a better way to organize my packages in the first place, without the naming redundancy?
UPDATE
So, I followed Avichal Badaya's instructions below, and removed one level of nesting. That is, I now have...
bagoftricks ├── bagoftricks │ ├── __init__.py │ └── bagoftricks.py ├── README.md └── setup.py
However, to call this package, I still have...
from bagoftricks.bagoftricks import geofind()
or
import bagoftricks
then
>>> bagoftricks.bagoftricks.geofind()
Rather than the desired....
from bagoftricks import geofind()
or
import bagoftricks >>> bagoftricks.geofind()
I cannot remove that extra layer of nesting. When I try, by analogy, to remove one more level of nesting, so that my module is flat, as:
bagoftricks ├── __init__.py ├── bagoftricks.py ├── README.md └── setup.py
I cannot build the package at all...
$ python setup.py build running build running build_py error: package directory 'bagoftricks' does not exist
What's the secret for natural imports like standard packages use, without redundant top-level name imports?
Organize imports into groups: first standard library imports, then third-party imports, and finally local application or library imports. Order imports alphabetically within each group. Prefer absolute imports over relative imports. Avoid wildcard imports like from module import * .
Packages In PythonPackages group similar modules in a separate directory. They are folders containing related modules and an __init__.py file which is used for optional package-level initialisation. __init__.py is executed once when a module inside the package is referenced.
Hence, if you want to get the top package name, you just need to get the first component of the path and import it using __import__ . Despite the variable name used to access the package is still called top_package , you can rename the package and if will still work.
The first level "bagoftricks" is fine. That's just the name of your "project" so to speak. In the you have a setup.py, and other files that tell the packaging systems what they need to know.
You can then have the code directly in this module, or in a src directory. You can even go as far as just having this structure:
bagoftricks ├── bagoftricks.py ├── README.md └── setup.py
But I would not recommend that, mostly because you might want to reorganize things later, and it's easier if you already have a "proper" package. Also most people, tools and docs assume you have a package, so it's easier.
So the minimum would be:
bagoftricks ├── bagoftricks │ └── __init__.py ├── README.md └── setup.py
With __init__.py
containing the functions you want to import. You then use these functions like this:
from bagoftricks import levenshtein, anotherfunction
Once that __init__.py
becomes too big, you want to split it up in several modules, giving you something like this:
bagoftricks ├── bagoftricks │ ├── __init__.py │ ├── anothermodule.py │ └── levenshtein.py ├── README.md └── setup.py
Your __init__.py
should then import the functions from the various modules:
from bagoftricks.levenshtein import levenshtein from bagoftricks.anothermodule import anotherfunction
And then you can still use them like like you did before.
with the updated structure you posted
bagoftricks ├── bagoftricks │ ├── __init__.py │ └── bagoftricks.py ├── README.md └── setup.py into bagoftricks/__init__.py import all functions that you need __init__.py from bagoftricks import geofind, levenshtein
into a different program you can do the follwing
from bagoftricks import geofind import bagoftricks; bagoftricks.geofind(); bagoftricks.bagoftriks.geofind()
note that you can import as well a wild card
from bagoftricks import *
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With