Search code examples
pythondatabaseargskeyword-argument

How to dynamically fetch tables from database?


There is a database with several tables. I'm trying to write a function to fetch them without explicitly indicating table names.

I have a function like this:

def get_fb_sql_tables():
    try:
        fb_data_table = pd.read_sql('SELECT * FROM FB_Data', con=engine)
        fb_meta_table = pd.read_sql('SELECT * FROM FB_Meta', con=engine)
        fb_basic_table = pd.read_sql('SELECT * FROM FB_Basic', con=engine)

        fb_data_table.reset_index(drop=True).drop_duplicates()
        fb_meta_table.reset_index(drop=True).drop_duplicates()
        fb_basic_table.reset_index(drop=True).drop_duplicates()

        return fb_data_table, fb_meta_table, fb_basic_table

    except Exception as e:
            logging.error("Exception occurred, check def get_fb_sql_tables", exc_info=True)

But I'm trying to make a function like this

def get_sql_tables(*tables):
    sql_tables = []

    try:
        for table in tables():
            table = pd.read_sql('SELECT * FROM {}'.format(table), con=engine)
            table .reset_index(drop=True).drop_duplicates()
            logging.info('Got {} tables successfully'.format(table))
            sql_tables.append(table)
            return sql_tables

    except Exception as e:
            logging.error("Exception occurred, check def get_sql_tables", exc_info=True)



sql_tables = ['FB_Data','FB_Meta']

for table in sql_tables:
    print(get_sql_tables(table))

I've tried with *args and **kwargs but it doesn't work.

It returns None objects.


Solution

  • If you have a for loop in your code you don't have to unpack the list of table names:

    import logging
    import pandas as pd
    
    # no need to unpack the list if you have for loop
    def get_sql_tables(tables):
        sql_tables = []
    
        try:
            for table in tables:
                # avoid same names for loop variable and inside the loop
                table_res = pd.read_sql('SELECT * FROM {}'.format(table), con=engine)
                table_res.reset_index(drop=True).drop_duplicates()
                logging.info('Got {} tables successfully'.format(table))
                sql_tables.append(table_res)
            # return need to be outside of the loop
            return sql_tables
        # generic exception is not a good practice - try to be specific
        except Exception as e:
            logging.error("Exception occurred, check def get_sql_tables", exc_info=True)
    
    # no need for second for loop
    sql_tables = ['FB_Data', 'FB_Meta']
    print(get_sql_tables(sql_tables))