How to call a script (module) from another directory in the Python Controller?

In the Python controller, I can type in a directory name with a dot that then follows the module name. This goes like an example:
example.someModule.Func

But if I type any directory name that precedes this example with the dot included, UPBGE reads it as a module, not a directory. Am I missing something here? I want to get UPBGE to read the directory set before the example as a directory, and then read the sub-directory as a sub-directory and import the module from there.

A good example:

exampledirectory.examplesubdirectory.SomeModule.Func

Which in theory, should import the example module mentioned here, but reads the directory portion as just a module (beginning part). How can I solve this and load a module from one directory back and a sub-folder, or a different directory altogether?

Sorry if I might be a little repetitive in this post, but I need a solution to this issue.

import FileA # don use .py in end python file in import
FileA.Main() # or FileA.name_you_function_in_python_fileA()

Treat it like a module: import file. This is good because it is safe, fast and easy to maintain. The code is reused the way it should be done. Most Python libraries work using multiple methods, stretched over many files. Highly recommended. Note that if your file calling file.py . import on should not include .the expansion is at the end.
The infamous (and insecure) exec command: insecure, hacker-like, usually the wrong answer. Avoid where possible.
execfile('file.py ') in Python 2
exec(open('file.py ').read()) in Python 3

1 Like

I tried to use the import module in tandem with a game property with expandPath, but it raises a ModuleNotFoundError. I want to make it import through a game property that defines the path, and another game property defines what script file to use, like a pointer.

The goal is to:

  • Use a game property to define the directory path
  • Use another game property to point to the script file (example.main) as a sample, and then load it through the import module.

But this just raises the ModuleNotFoundError. How to import a script via expandPath and game properties?

you need concatenation of the strings - just sum strings
own[‘path_scripts’]
own[‘script_name’]
path = expandPath(“//”+own[‘path_scripts’]+“/”+own[‘script_name’])
if in you path or names folders use numbers (path/folder1/folder2) - use convert numbers to string - expandPath(“//folder”+str(1)), if you need insert name script in run function - assign name to string variable and translate to method -
string = own[‘function_name’] #string global variable
fileA.string()

try this

import bge
path = bge.logic.expandPath("//")+"exampledirectory"
import sys
sys.path.append(path)

only run this one time at the very start of you Game/Project.

or to be on the safe side

import bge
path = bge.logic.expandPath("//")+"exampledirectory"
import sys

if path not in sys.path:
    sys.path.append(path)

Update: The sys.path comes up with None. Weird, I’ve got string properties and a path, so why does it come up with a None reading? Shouldn’t it return the path?

I’m not sure if this helps but I made this video to explain how to structure your game scripts outside of the .blend file when you’re using GameObjects and PythonComponents classes.

Here’s how I do it:

BGE/UPBGE loads in python scripts attached to a logic brick in module mode as a “python module”. Therefore, in order to load scripts inside the same module, python has some special syntax.

My game directory usually looks like this:

  • Game.blend
  • scripts (folder)
    • main.py
    • utilities.py
    • other_files.py

main.py will have a “main game function” called runGame(cont):.

The Game.blend file has a logic brick with the string scripts.main.runGame to run this function from main.py

Now, imagine that utilities.py has a class or function that we want to call from main.py. Let’s say, a function called spawnCar(). All we need to do to import it is “relative dot” notation. Here’s what utilities.py looks like:

def spawnCar():
    print("hehe spawned a car")

:smiley:

For example, here’s how main.py might look like:

from . import utilities
def runGame(cont):
    own = cont.owner
    # do stuff
    utilities.spawnCar()

or this:

from .utilities import spawnCar
def runGame(cont):
    own = cont.owner
    # do stuff
    spawnCar()

Both of these should work fine. Remember, you need both of these files to be within a folder so that they can be considered a single module. In this case, they’re both in the scripts folder.

Good luck!