How to import variables from a Python file?

Say I have a file foo.py with the following contents:

a = 1
b = 2
c = 'xyz'

Is there a way to “import” these variables in my document dynamically? I’d like to avoid going through json or another intermediate format if possible.

If the source file is so simple you could parse it as TOML data:

#toml("a.py")

or write your own parser:

#let load-vars(file) = {
  let source = read(file)
  let vars = (:)
  for line in source.split("\n") {
    let assignment = line.match(regex("^\s*(.*?)\s*=\s*(.*?)\s*$"))
    if assignment != none {
      vars.insert(..assignment.captures)
    }
  }
  return vars
}

#load-vars("a.py")

For more complex cases the pyrunner package might do the job:

#import "@preview/pyrunner:0.2.0" as py

// Equivalent to #let source = read("a.py")
#let source = ```
a = 1
b = 2
c = 'xyz'
```.text

#py.block(source + "\na")

#py.block(source + "\nb")

#py.block(source + "\nc")

but see the package documentation for limitations (in particular you can’t run Python code that uses third-party packages).

2 Likes

This is more Python than Typst, but the following can give you all the variables from the current module, which may be useful:

{k: v for k, v in globals().items() if not k.startswith('__')}

applied to your example, you’ll get

{'a': 1, 'b': 2, 'c': 'xyz'}

I think the easiest way from there would still be converting that to JSON (or another Typst readable format), but there are probably other paths open as well.