Optimizing imports in python

I have a folder that contains several files with the extension. py and inside each file has a dictionary with the data of the monsters I need to start. However, the greater the amount of monsters I create, the Greater this list of imports will get. Do you have any way to import the entire folder and all dictionaries at once?

from units import Monster
from data.creatures.monster_list.rat import rat
from data.creatures.monster_list.snake import snake
from data.creatures.monster_list.scorpion import scorpion
from data.creatures.monster_list.lion import lion
from data.creatures.monster_list.wolf import wolf
from data.creatures.monster_list.warlock import warlock
MONSTERS = [rat,snake,scorpion,lion,wolf,warlock]
Author: Lucas João, 2019-07-26

2 answers

The ideal here is to have a scheme to do a dynamic import of files in the same folder. This code can run in the __init__ file of a folder - and as soon as you import that folder as a package, all the .py files in it are read.

Traditionally, the way to import a module from a string (i.e., a data, in contrast to the module name typed directly into the program as a parameter to the import command) is with the call __import__. Pr issues historical, however, its use is more complicated than it needs to be-with a single parameter it ends up returning the root package of the string you passed (in your example, the package data)

Then, generically, you can make an import that brings everything you have in the directory. In your case, since you want to make the imported classes available in a data structure (a list), it may be worth doing something more targeted:


from importlib import import_module
from pathlib import Path

def import_creatures(package_name):
    root_package = import_module("package_name")
    package_path = Path(root_package.__file__).parent
    creature_classes = []
    for source_file in package_path.glob("*.py"):
        module = import_module(source_file)
        name = source_file.stem
        # Tenta importar a classe se tiver nome comecando com letra maiuscula também
        cls = getattr(module, name, getattr(module, name.title(), None))
        if not cls:
            continue
        creature_classes.append(cls)
    return creature_classes

MONSTERS = import_creatures("data.creatures.monster_list")


This code always tries to catch the class that has the same name as the file, as in your example - but you can also introspect the module (by taking module.__dict__.items() for example), and take all the objects that are subclass of a specific class - if all your own inherit from "Monster" for example - then you can safely have more than one definition of Monster per file, and still have freedom to name the classes.


Changing the subject -what about this game? Will he be released? Is it in a public repository? Prune contribute?? :-)


Another note, as the first package of your import name is data, probably your project is not yet structured itself as a Python package that can be installed - and it will only work if you run the main program of the folder where it is (and there, in that folder has the folder data, but for Python it is a package independent of your project).

Ideally, your project directory has a __init__.py, and you work from a folder above, where with a minimum setup.py file, you can type pip install --editable . so that your game is seen as "whole". In this case, the imports will change to meujogo.data.creatures.... , or with a "."on the front - .data.creatures... - but the whole project gets a" feeling " of a single product - it's much cooler.

O setup.py what you need is something like:

from setuptools import setup

setup(
    name='route_optimizer',
    version='0.1',
    author='Thomas Caio',
    py_packages=['meujogo'],
    install_requires=[],

)
 7
Author: jsbueno, 2019-07-27 02:43:50

A simple way to do imports is to import all files from the folder:

from data.creatures.monster_list import *

The problem is that this would import the files and to access the classes would need to do Arquivo.Classe. If that's not a problem for you, it's a great solution.

 0
Author: Rafael Setton, 2020-05-21 11:52:48