3
$\begingroup$

I have a text buffer that is loaded from an external file. In that same text buffer I need to write code that imports some functions from another file in the same directory as the one in the text buffer.

  • Hardcoding that path in the source is unsuitable because the file may live in different directories on different users' machines.
  • Command-line arguments seem like a a horrid Rube Goldberg kludge and a horrible user experience.
  • a file selection dialog is also poor user experience.

Java has a mechanism similar to what I want using class.getResource(relPath) (imagine if tomcat gave you a file selection dialog box when it needed to load the Spanish translations for localized string resources)

What is the best python technique to accomplish this?

$\endgroup$
2
$\begingroup$

You can add the text file's folder to the system path, which will enable you to import from that path.

I'd also suggest to extract the folder path via os.path.dirname.

Short example to clarify:

import sys
from os.path import dirname
textFilePath = "/home/me/somewhere/textfiles/text1"
textFileFolder = dirname( textFilePath ) # = "/home/me/somewhere/textfiles"

sys.path.append(textFileFolder)

import someFileThatExistsInTextFolder
$\endgroup$
  • $\begingroup$ The piece that is missing from your solution is the method for determining the text file's folder. $\endgroup$ – Mutant Bob Aug 15 '15 at 19:43
  • $\begingroup$ If you have the full path for the file (which you need if you want to open that file), then you can get the folder via os.path.dirname( textFilePath ) $\endgroup$ – TLousky Aug 15 '15 at 20:33
  • $\begingroup$ hardcoding textFilePath inside the source will be wrong when someone else checks out the git repository into a different directory. $\endgroup$ – Mutant Bob Aug 17 '15 at 2:57
  • $\begingroup$ OK, so there are many other dynamic ways to accept a path into your script. You can use command line arguments when running from the terminal (read about sys.argv and running blender from the command line), you can create an addon and use the file browser to select a path before executing your script as an operator (read about blender addons here blender.org/api/blender_python_api_2_74_release/…), and there are many other ways, depends on limitations and needs. $\endgroup$ – TLousky Aug 17 '15 at 5:41
0
$\begingroup$

When I broadened the search to python in general (instead of blender specifically) I came across How do I get the path and name of the file that is currently executing? . It turns out blender does provide mildly useful results when inspecting from inside a text buffer and I was able to derive the following solution:

def dir_of_this():
    raw_path = inspect.getfile(inspect.currentframe())
    l = len(bpy.data.filepath)
    if raw_path[:l] == bpy.data.filepath:
        # Blender gives us a path consisting of the .blend file name plus the name of the text buffer inside the .blend.
        # Mildly awkward, but still usable.
        buf_name = raw_path[l+1:]
        #print("buffer is %s"%buf_name)
        raw_path = bpy.data.texts[buf_name].filepath
    return os.path.dirname(raw_path)

p1 = dir_of_this()
if not p1 in sys.path:
    sys.path.append(p1)

import boilerplate

import importlib               # optional 
importlib.reload(boilerplate)  # optional

from boilerplate import *
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.