How can module be visible from one import and not visible from another?
Question: So I've got an application that's using `pymysql`, the pure python mysql
client implementation. Before I go into my response, I'd like to stress the
fact that I am not open to using a different mysql driver.

I have a module implementing a data structure that's backed by MySQL. The gist
of the module is as follows:

    
    
    import pymysql
    class Whatever:
        def __init__(self):
            # Debug statement
            print dir(pymysql)
            # use the cursors submodule
            self.conn = pymysql.connect( ... , cursorclass=pymysql.cursors.DictCursor)
    

When I import this in my test file, everything is fine. Here is the output of
the `print` statement. In particular, I draw your attention to the cursors
module:

    
    
    ['BINARY', 'Binary', 'Connect', 'Connection', 'DATE', 'DATETIME', 'DBAPISet', 'DataError', 
    'DatabaseError', 'Date', 'DateFromTicks', 'Error', 'FIELD_TYPE', 'IntegrityError', 
    'InterfaceError', 'InternalError', 'MySQLError', 'NULL', 'NUMBER', 'NotSupportedError', 
    'OperationalError', 'ProgrammingError', 'ROWID', 'STRING', 'TIME', 'TIMESTAMP', 'Time', 
    'TimeFromTicks', 'Timestamp', 'TimestampFromTicks', 'VERSION', 'Warning', '__all__', 
    '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 
    '__version__', 'apilevel', 'charset', 'connect', 'connections', 'constants', 'converters', 
    'cursors', 'err', 'escape_dict', 'escape_sequence', 'escape_string', 'get_client_info', 
    'install_as_MySQLdb', 'paramstyle', 'sys', 'thread_safe', 'threadsafety', 'times', 'util', 
    'version_info']
    

When I import the module from my main file, I get an `AttributeError`:

    
    
    Traceback (most recent call last):
      File "xxx.py", line 72, in <module>
        passwd='', db='test_db')
      File "yyy.py", line 26, in __init__
        passwd=passwd, db=db, cursorclass=pymysql.cursors.DictCursor)
    AttributeError: 'module' object has no attribute 'cursors'
    

The output of the `dir` print is as follows:

    
    
    ['BINARY', 'Binary', 'Connect', 'Connection', 'DATE', 'DATETIME', 'DBAPISet', 
    'DataError', 'DatabaseError', 'Date', 'DateFromTicks', 'Error', 'FIELD_TYPE', 
    'IntegrityError', 'InterfaceError', 'InternalError', 'MySQLError', 'NULL', 'NUMBER', 
    'NotSupportedError', 'OperationalError', 'ProgrammingError', 'ROWID', 'STRING', 'TIME', 
    'TIMESTAMP', 'Time', 'TimeFromTicks', 'Timestamp', 'TimestampFromTicks', 'VERSION', 
    'Warning', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 
    '__path__', '__version__', 'apilevel', 'charset', 'connect', 'constants', 'converters', 
    'err', 'escape_dict', 'escape_sequence', 'escape_string', 'get_client_info', 
    'install_as_MySQLdb', 'paramstyle', 'sys', 'thread_safe', 'threadsafety', 'times', 
    'version_info']
    

Notably, `cursors` is absent. Checking `pymysql.__file__` is the same in both
cases, and the output is:

    
    
    __init__.py     charset.py  connections.py  constants   converters.pyc  cursors.pyc err.pyc     times.py    util.py
    __init__.pyc    charset.pyc connections.pyc converters.py   cursors.py  err.py      tests       times.pyc   util.pyc
    

Clearly `cursors.py` is there. So what gives?


Answer: You need to add an explicit `import pymysql.cursors` at the top of your file.

the `cursors` subpackage is not listed in the `pymysql`'s `__all__` and thus
isn't imported when you do just `import pymysql`.

