4
$\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 Answers 2

4
$\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$
4
  • $\begingroup$ The piece that is missing from your solution is the method for determining the text file's folder. $\endgroup$
    – Mutant Bob
    Aug 15, 2015 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, 2015 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, 2015 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, 2015 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$
1
  • $\begingroup$ This works if you remember to: import inspect, os $\endgroup$
    – trygvrad
    Apr 22, 2022 at 12:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .