Michał Góral
Michał Góral

Reputation: 1517

Import symbols starting with underscore

I'm writing a simple Python library in which I have several "private" functions starting with underscore:

def _a():
    pass

def _b():
    pass

def public_interface_call():
    _a()
    _b()

This way my library users can simply do from MyLib.Module import * and their namespace won't be cluttered with implementation detail.

However I'm also writing unit tests in which I'd love to test these functions separately and simple importing truly all symbols from my module would be very handy. Currently I'm doing from Mylib.Module import _a _b public_interface_call but I wonder if there's any better/quicker/cleaner way to achieve what I want?

Upvotes: 17

Views: 20295

Answers (3)

normanius
normanius

Reputation: 9792

The best and most common solution for your problem already has been given:

import MyLib.Module as mm

If one still wants to make use of the variant from MyLib.Module import *, there is the possibility to override its default behavior: Add a list __all__ to the module's source file MyLib/Module.py and declare which objects should be exported.

Note that you need to do this for every object you want to be visible. This does not affect the behavior of the other import mechanism above.

Example:

# MyLib/Module.py
__all__ = ["_a", "_b"]

def _a(): pass 
def _b(): pass
def  c(): pass

# ...

# Import
from MyLib.Module import *
# => this imports _a() and _b(), but not c()

To specify a package index __all__ can make sense to control which submodules should be loaded when importing a package. See here for more information, or this SO thread on a related question.

Upvotes: 1

Jet Blue
Jet Blue

Reputation: 5281

According to docs,

There is even a variant to import all names that a module defines:
from fibo import *
...
This imports all names except those beginning with an underscore (_).

Not sure why this is the case however.

Upvotes: 5

Michał Góral
Michał Góral

Reputation: 1517

I'm not sure if it was a blackout or something when I wrote that question but today I realized (inspired by Underyx's comment) that I can simply do this:

import MyLib.Module

MyLib.Module._a()
MyLib.Module._b()

Or even to shorten things a little (because I'm a lazy bastard):

import MyLib.Module as mm

mm._a()
mm._b()

Upvotes: 15

Related Questions