Trying to understand __init__.py combined with getattr
Asked Answered
A

1

7

I am trying to understand a piece of Python code.

First, I have the following file structure:

folder1--
   model
     __init__.py
     file1.py
     file2.py
  __init__.py

The __init__.py in the folder folder1 has nothing. The __init__.py in the folder model has the following:

import os
files = os.listdir(os.path.split(os.path.realpath(__file__))[0])
files.remove('__init__.py')
for file in files:
    if file.endswith('.py'):
        exec('from .{} import *'.format(file[:-3]))

With that said, I have some code in python that uses all the above Now, I am trying to understand the following code

from folder1 import model as mymodel

My first question is what does this do? I mean model is a folder name right? it is not an object. or is it? What is exactly importing as mymodel here?

then later in the same code it says

global args, cfg, is_fov120
args = parser.parse_args()
model = getattr(mymodel, args.arch)(sync_bn=False)

Apparently there is some arguments called arch. What is happening here and what does model have after this?

Edit

When I do print(mymodel)

I get <module 'folder1.model' from 'C:\\path\\to\\folder1\\model\\__init__.py'>

Investigating even more I can see that I have imported all the objects from the files in the folder model.

mymodel.files gives the list of files in the folder, and I can call mymodel.somevariable if some variable was defined in file1.py or file2.py. As for classes I have to create an object first like x=mymodel.aClass() and then I can access the elements of the object x.someElement.

Finally I found out that getattr is getting a class from the files inside model and I can guess that the sync_bn=False is a parameter to the constructor of that class.

So in the end, model is an object of that class.

Anemography answered 31/7, 2020 at 0:27 Comment(0)
A
5

If you desire to have a folder as a python module, the folder must contain an __init__.py, even if it is empty. Then you can import the rest.

import os
files = os.listdir(os.path.split(os.path.realpath(__file__))[0]) #get the folder's content
files.remove('__init__.py')                                      #remove __init__.py since it is empty
for file in files:                                               #loop through the files
    if file.endswith('.py'):                                     #if it is a python file
        exec('from .{} import *'.format(file[:-3]))              #import

The above code, imports every other .py files than the __init__, which is empty.


from folder1 import model as mymodel

Here folder1 is the module, and model is the object you imported from (folder) model in this case, since it is now imported to folder1's __init__.py, and now it is part of folder1 (which is a module as discussed).


model = getattr(mymodel, args.arch)(sync_bn=False)

This line is equal to: mymodel.attr, where attr is the desired attribute of the object. Can you please post more code around the getattr, since I can't tell what args.arch are refering to.

As Pyzard suggested, the getattr method gets an attribute, which is a function, since it is getting called, and method is the value that this function returned. In this case sync_bn is irrevelant, but knowing more about args.arch would still help.


More about the getattr function, how import works. Better explanation of how init.py works.

Aestivate answered 31/7, 2020 at 0:49 Comment(4)
It looks like the getattr would get an attribute which is a function or method because it's getting called.Hundredfold
model is the object I imported from folder model? But there is not anything called "model" in any of the py files inside the folder model... which object are you refering?Anemography
In the first section, the code imported model/file1 and model/file2, and now folder1/__init__ contains model.file1 and model.file2.Aestivate
I added a print I didAnemography

© 2022 - 2024 — McMap. All rights reserved.