Warning

Most of the documentation was written prior to version 0.5 and needs to be updated. This work has now started for version 0.7 and we aim to have it completed before version 0.8 is available.

Why import *?

Tip

As explained below, while I recommend to use import * for easier interactions, you might prefer the next best alternative which is to import the Friendly object by doing:

from friendly... import Friendly

In many pages of this documentation, you will see that I suggest to use something like from friendly.X import *. This is often mentioned as being a bad practice, since it “pollutes” the current namespace with various names whose origin become difficult to trace.

If you have tried the Friendly console, or read the previous pages in this documentation, you will have seen various useful functions such as what(), where(), why(), etc., which can be used in an interactive mode. You can think of these functions as useful additions to Python’s builtins, such as dir(), vars(), etc. These functions are meant to be used in interactive sessions.

Speaking of which, here are the names immediately available from the default namespace in a python interpreter:

>>> print(dir(__builtins__))
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '_', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
>>> len(dir(__builtins__))
154

Using import * with friendly-traceback adds 19 names to the environment so that they are immediately available in an interactive session:

>>> dir()
['Friendly', '__builtins__', 'back', 'explain', 'friendly_tb', 'get_include', 'get_lang', 'hint', 'history', 'python_tb', 'set_debug', 'set_formatter', 'set_include', 'set_lang', 'set_prompt', 'show_paths', 'what', 'where', 'why', 'www']

>>> len(dir())  # includes '__builtins__'
20

[Note: Friendly might add 2 to 4 additional names to select a specific theme.]

The usual suggested alternatives to importing everything are the following:

  1. Import only what’s needed. For example:

    from friendly.X import what, where, why
    
  2. Import as a namespace; something like:

    from friendly import X
    # or
    import friendly.X as Y
    

One problem with the first suggestion is that, as shown above, friendly/friendly-traceback has quite a few other functions that are potentially useful; nothing like the 154 names shown above but still too many to type explicitly. So this might require another import statement, from friendly.X import something_else when wanting to use something_else. Trying to import all the possibly relevant functions by explicitly naming them in a single import statement is not really practical.

Using the second alternative means that, instead of simply writing why(), one might have to write something like X.why(). A potential problem with this second approach is that friendly.X might contain many other names, such as __path__, __spec__, etc., as well as other functions which are meant to be used only within module X which are not useful but would show up when doing something like dir(X) or help(X).

When creating a special module friendly.X for a specific environment, such as friendly.idle to be used with Python’s IDLE, I define __all__ so that only the relevant objects are imported when doing from friendly.X import *.