Python how to access parent's modules and functions from child module

Viewed 330

I have three files that all contain classes with the same names but slightly different definitions. Some methods in these classes are identical across all three files, so I abstracted them out to another file, utils.py, where they are defined within a "template" version of the original class. The problem is that these methods invoke functions and modules that exist in the original files but not this new one.

My original approach was to use multiple class inheritance, which would initialize the template class within the scope of the parent class, allowing access to all the functions and modules it requires. However, I was instructed to avoid multiple class inheritance and to simply import the utils file.

Importing does not apply the same scoping logic as mentioned above with inheritance. So here arises my problem. I have created a small example to show what I mean. I am using a module called datajoint. You don't need to know much about it except that a schema is basically a table or collection of tables in a database.

schemas.py

import datajoint as dj
from datetime import datetime
import utils

dj.conn()
schema = dj.Schema('adib_example1')
schema.drop()
schema = dj.Schema('adib_example1')

def test_print():
    print("test")

@schema
class Subject(dj.Lookup):
    definition = """
    subject_id: int
    """
    contents = [dict(subject_id=1)] 
    
@schema
class Session(dj.Computed):
    definition = """
    -> Subject
    time: varchar(30)
    """
    
    def make(self, key):
        utils.SessionTemplate.make(self,key)
        
Session.populate() # invokes Session's make(), passing Subject's primary key

Approach 1

Import scoping not working like inheritance

utils.py

class SessionTemplate():
    
    @staticmethod
    def make(table, key):
        test_print() # parent function usage example
        table.time = f"{datetime.now()}" # parent module usage example
        new_entry = dict(**key, time=table.time)
        table.insert1(new_entry)

error

Traceback (most recent call last):
  File "/home/.anaconda/imported_make/schemas.py", line 30, in <module>
    Session.populate() # invokes Session's make(), passing Subject's primary key
  File "/opt/conda/lib/python3.9/site-packages/datajoint/autopopulate.py", line 153, in populate
    make(dict(key))
  File "/home/.anaconda/imported_make/schemas.py", line 28, in make
    utils.SessionTemplate.make(self,key)
  File "/home/.anaconda/imported_make/utils.py", line 5, in make
    test_print() # parent function usage example
NameError: name 'test_print' is not defined

Approach 2

Importing schemas.py into utils.py works, but requires including schemas. before every imported function and module, which is not practical in my case.

utils.py

import schemas

class SessionTemplate():
    
    @staticmethod
    def make(table, key):
        schemas.test_print() # parent function usage example
        table.time = f"{schemas.datetime.now()}" # parent module usage example
        new_entry = dict(**key, time=table.time)
        table.insert1(new_entry)

Approach 3

Import using * to avoid having to add schemas. before each parent function/module somehow does not provide access to the parents modules and functions.

from schemas import *

class SessionTemplate():
    
    @staticmethod
    def make(table, key):
        test_print() # parent function usage example
        table.time = f"{datetime.now()}" # parent module usage example
        new_entry = dict(**key, time=table.time)
        table.insert1(new_entry)

error

Traceback (most recent call last):
  File "/home/.anaconda/imported_make/run.py", line 1, in <module>
    import schemas
  File "/home/.anaconda/imported_make/schemas.py", line 30, in <module>
    Session.populate() # invokes Session's make(), passing Subject's primary key
  File "/opt/conda/lib/python3.9/site-packages/datajoint/autopopulate.py", line 153, in populate
    make(dict(key))
  File "/home/.anaconda/imported_make/schemas.py", line 28, in make
    utils.SessionTemplate().make(self,key)
  File "/home/.anaconda/imported_make/utils.py", line 7, in make
    test_print() # parent function usage example
NameError: name 'test_print' is not defined

I know import * is bad practice, but it would have been fine in this instance if it worked, and I'm not sure why it doesn't.

1 Answers

boss.py

class tasks():
   def job1(input):
      // do something
      return output
   def job2(input):
      // do something
      return output

worker.py

import boss.tasks
from boss.tasks import job1, job2

input_value = "xyz"

output1 = boss.tasks().job1(input_value)
output2 = boss.tasks().job2(input_value)
Related