# Importing modules for private use in Python [closed]

There's something I completely dislike when importing a module in an interactive Python shell, typing the name of the module, hitting tab and getting the automatic completion cluttered with other modules that the module itself had imported (but are internal implementation details that are not really useful for me).

Example:

## a.py

import os
import datetime

def foo():
now = datetime.datetime.now()
print os.path.join(map(str, (now.year, now.month, now.day)))

$ipython Python 2.7.15rc1 (default, Nov 12 2018, 14:31:15) Type "copyright", "credits" or "license" for more information. IPython 5.5.0 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython's features. %quickref -> Quick reference. help -> Python's own help system. object? -> Details about 'object', use 'object??' for extra details. In [1]: import a In [2]: a. a.datetime a.py a.foo a.pyc a.os I don't care that module a depends on datetime and os, that is distracting me from what the module provides (foo). So I have started to make my imports private, like this: ## a.py import os as _os import datetime as _datetime def foo(): now = _datetime.datetime.now() print _os.path.join(map(str, (now.year, now.month, now.day))) ## shell$ ipython
iPython 2.7.15rc1 (default, Nov 12 2018, 14:31:15)

IPython 5.5.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import a

In [2]: a.
a.foo
a.py
a.pyc

Is this considered pythonic at all? I feel like it's a little bit too verbose, but I think simplifying the end user's experience should be above saving some extra tokens per import.

## NO

This is not pythonic... and this is ugly... aaah, I can't get that code out of my head...

## There is this thing called __all__

### 1. How does it work

Make a list, put everything you want to make public in it and boom, you're done.

### 2. What it doesn't do

You will still be able to do my_module.datetime if datetime is imported in my_module

### 3. What does it do

When you do from my_module import *, it doesn't import datetime. Autocomplete will use __all__ if it exist.

### 4. What are some great conventions that goes with this

You can put it in the __init__.py if it exists

### 5. Show me

Numpy uses the warning module but it doesn't pollute your namespace.

>>> import numpy
>>> 'warnings' in dir(numpy)
True
>>> 'warnings' in numpy.__all__
False
>>> from numpy import *
>>> warnings
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'warnings' is not defined

# Update:

Every autocomplete in the world* uses __all__ except ipython which uses "some custom logic"(github issue). So I believe the most pythonic solution is go complain on the github issue.

*extrapolation of "the editors I use"

• I already considered using __all__ for this purpose, but I rejected it because: 1. doing wildcard imports is usually discouraged (see PEP-8) 2. the default mechanism for introspection is dir, so if it shows in dir it makes sense that it is public. 3. it needs to be kept in sync manually. p.s. your hubris is also quite ugly and I can't get it out of my head either, so I guess we are even. Feb 28 '19 at 15:03
• @fortran "if it shows in dir it makes sense that it is public", What ? Everything shows in dir, public or private, beginning with _ or not. Also, that's how python works, if you like it or not. If you do import antigravity, you can access sys by doing antigravity.webbrowser.subprocess.os.sys for example. __all__ is the way to go, and from what I've heard, that bug in IPython will be solved in the future. So no your solution is not pythonic, but who needs a pythonic solution when you have a solution that works. Feb 28 '19 at 15:42
• You are absolutely correct about dir (I was thinking about something else), but the other two points still hold. I was aware that my solution wasn't Pythonic and that's why I asked for a better one, but yours is more flawed and it came with some attitude that was totally unasked for. Feb 28 '19 at 15:56
• I'm sorry, I was trying to be helpful, if I was not, I failed. I didn't want to criticise you personally, I wanted to criticise your code. I apologise if I've hurt your feelings. At least we agree your solution is an ugly workaround. But, my point is, use __all__ because otherwise, when IPython is fixed, you will still have ugly code. Writing ugly code to have slightly better autocompletion (until fixed) isn't worth it in my opinion. Feb 28 '19 at 16:09