Python relative/absolute import (again)
Question: This topic has been covered several times but I still can't get my package to
work. Here is the situation: I've got a package in which a `logging` module
takes care of setting up the logging. So clearly, `mypackage.logging`
conflicts with Python `logging` from the standard library.

The directory' structure:

    
    
    ├── mypackage
    │   ├── __init__.py
    │   ├── logging.py
    └── script.py
    

**mypackage.__init__**

    
    
    import logging
    from . import logging as _logging
    
    logger = logging.getLogger(__name__)
    
    def main():
        _logging.init_logging()
        logger.info("hello")
    

**mypackage.logging**

    
    
    """logging - Setup logging for mypackage."""
    
    import copy
    import logging
    import logging.config
    
    
    _DEFAULT_LOGGING_CONFIG_DICT = {
        'version': 1,
    
        'formatters': {
            'verbose': {
                'format': '%(asctime)s - %(name)s::%(levelname)s: %(message)s',
            },
            'simple': {
                'format': '-- %(message)s',
            },
        },
        'handlers': {
            'console': {
                'class': 'logging.StreamHandler',
                'level': 'DEBUG',
                'formatter': 'simple',
            },
            'file': {
                'class': 'logging.FileHandler',
                'filename': 'oprpred.log',
                'mode': 'w',
                'formatter': 'verbose',
            },
        },
        'loggers': {
            'oprpred': {
                'level': 'INFO',
            },
        },
        'root': {
            'level': 'INFO',
            'handlers': ['console', 'file'],
        },
    }
    
    def init_logging(verbose=False):
        """Initialize logging.
    
        Set the log level to debug if verbose mode is on.
        Capture warnings.
        """
        d = default_logging_dict()
        if verbose:
            d['root']['level'] = 'DEBUG'
            d['loggers']['oprpred']['level'] = 'DEBUG'
        logging.config.dictConfig(d)
        logging.captureWarnings(True)
    
    
    def default_logging_dict():
        return copy.deepcopy(_DEFAULT_LOGGING_CONFIG_DICT)
    

**script.py**

    
    
    import mypackage
    mypackage.main()
    

Finally, this is the error message I'm getting:

    
    
    $ python3 script.py                                                                                                                                                                     [11:09:01]
    Traceback (most recent call last):
      File "script.py", line 4, in <module>
        mypackage.main()
      File "/Users/benoist/Desktop/test_logging/mypackage/__init__.py", line 8, in main
        _logging.init_logging()
    AttributeError: module 'logging' has no attribute 'init_logging'
    

Final remark, I noticed that if in `mypackage.__init.py__` I import
`mypackage.logging` prior to the standard library `logging`, it works. I don't
want to do that since it is against Python PEP8 recommandations:

> Imports should be grouped in the following order:
>
>   1. standard library imports
>   2. related third party imports
>   3. local application/library specific imports
>

Any help would be greatly appreciated.

Ben.

P.S. I'm using Python 3.5.1.


Answer: The way I deal with this specific issue of using a custom logging module is to
import all the logging functions into my custom module. Now you can also
reimplement module level functions with customized versions as well.

For example:

    
    
    """logging - Setup logging for mypackage."""
    
    import copy
    from logging import *
    import logging.config
    
    
    _DEFAULT_LOGGING_CONFIG_DICT = { ... }
    
    def init_logging(verbose=False):
        ...
    
    def default_logging_dict():
        ...
    

Now you only need to import your custom module.

    
    
    from . import logging
    
    log = logging.getLogger()
    

  
An alternative to using `from logging import *` is to reimplement any commonly
used functions from the built in logging module.

    
    
    import copy
    import logging
    
    def getLogger(*args, **kwargs):
        logging.getLogger(*args, **kwargs)
    

If you need to reach logging function that you have not reimplemented you can
call through to the builtin logging module, for example:
`logging.logging.addLevelName(...)`.

