Optimizing Imports in python

Asked

Viewed 312 times

3

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 that I need to start. However, the more monsters I create, the bigger this list of Imports gets. Is there any way to import all the folder and all the 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]
  • 2

    Why is each dictionary set in separate files? Could you set them all in the same file?

  • 1

    Could, but I wanted to leave it separate to facilitate the modifications and not to be a single giant file.

2 answers

7


The ideal thing is to have a schema to make a dynamic import of files in the same folder. This code can run in the file __init__ from a folder - and as soon as you import that folder as a package, all the files .py of 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 for the command import) is with the call __import__. Historical questions, 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, in a generic way, it is possible to make an import that brings everything you have in the directory. In your case, as you want to make the imported classes available in a data structure (a list), it might 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 get the class that has the same name as the file, as in your example - but it is also possible to insert the module (taking module.__dict__.items() for example), and take all objects that are subclass of a specific class - if all of yours inherit from "Monster" for example - then you can quietly have more than one monster definition per file, and still have freedom to name the classes.


Changing the subject -and this game? Will be released? Is in public repository? We can contribute?? :-)


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

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

The setup.py you need is something like:

from setuptools import setup

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

)
  • Po... Thanks! I’m making this game with the intention of practicing POO. I’m hitting myself to share on github, I wanted to leave an audience so people can help with tips. I’m new in the area and this import business always breaks my legs.

  • Cool - precisely if you want to use P.O.O. were not to be "dictionaries" with the data of the montros - let’s see if we pass them to subclasses

  • It is that with the dictionary I can store the data of the monsters in a variable, it was the way I thought to be able to return new instances of monsters, just passing the data of them. https://github.com/ThomasCaio/.RPG I got the project on github. Take a look at it!

  • 1

    no - the way you’re thinking dictionaries is what you’re supposed to do with subclasses - classes you inherit from the monster class. And what you’re creating as "instances" -should be these classes as well. (for anyone following, is on github here: https://github.com/ThomasCaio/.RPG/tree/9f6f38a7d10303b0bed7de434a3c279c266d57ae

  • If you can give me an example of this method to create new monster instances.

0

A simple way to make Imports is to import all files from the folder:

from data.creatures.monster_list import *

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.