Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to structure python packages without repeating top level name for import

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?

like image 702
Mittenchops Avatar asked Jul 03 '13 20:07

Mittenchops


People also ask

How do you organize imports in Python?

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 * .

How are Python packages organized?

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.

How do you define a top level package in Python?

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.


2 Answers

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.

like image 173
Lennart Regebro Avatar answered Sep 29 '22 03:09

Lennart Regebro


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 * 
like image 42
silviud Avatar answered Sep 29 '22 02:09

silviud