RAM Concept API "future feature is not defined:annotations"

Hi all, I’m currently trying to run a python script that grabs information from a RAM Concept model using its API. I’ve put this script in my lib folder and I refer to it in my PyRevit script using this line.

from get_ram_tendons import get_ram_tendons

and this is the error I get:

So far I’ve found that I cant use any external python libraries when running the script straight from PyRevit. I’ve found a way around most of my problems but I cant seem to avoid this one, and its pretty critical for what I’m trying to do. Is there a way to run this code or is there a workaround required?

Any help would be much appreciated!

Hi @zstructure, welcome to the community!!

Your problem is not with external libraries, but with python versions…
__future__ imports are part of the standard library, and if you take a look at the table on that page you’ll see that the annotations feature is suported only from python 3.7.

In fact, typing annotations only work with recent python versions, so you either have to drop them altogether to make your script work with ironpython, or you need to run your script with the cpython engine.

1 Like

Hi Andrea,

Thanks for your response!

My understanding is future imports is only in Python 3.7 and not other versions, I’m currently running Python 3.12.

I don’t think I have the option to run the script without this line since it’s from the RAM Concept API. Thing is when I use the RAM API in a python script outside the pyRevit environment it works fine, but when I run it from a pushbutton in pyRevit this error occurs.

Can you elaborate on the cpython engine?

Would really love to get this working, thanks!

PyRevit doesn’t use the python you installed in your system, but an interpreter (IronPython) that is embedded into pyrevit itself. This interpreter is not the same as the vanilla python, usually referred as cpython because it is written in C: it is written on c# to be able to run python scripts inside the .net runtime (used bt Revit).

There are different versions of the interpreter (pyRevit calls them engines) available, one of which allows you to run the cpython via a library called python.net, but the support is not that great at the moment.

Please take a look at the documentation to understand how pyRevit works and how to use the CPython engine

pyRevit website where you will find all the links including the one for the documentation

to add to that, if you need to run something outside of pyRevit/Revit and use your python install, you can do it using subprocess with the call method

exemple for a script to run a specific command line

from subprocess import call
call('cmd /c "pyrevit extensions update NameOfUrExtension --token="azerty""', shell=True)

Thanks, this makes sense, and it looks like the RAM Concept API is now working in PyRevit, thanks!

But what I couldn’t find is how to install modules/python packages into the CPython site-packages folder. Is there any guidance on how to do this?

I ask because I tried to use an external library like easygui to open the file dialogue for a user to select a file path of a RAM model, since I cant use pyrevit forms with CPython.

Please search the forum, you’ll find that this is currently not possible.
What @Jean-Marc suggested is the current workaround for this:

  • you write an external cpython script with the libraries you want; this script would output the data to stdout (with print or other means) or save it to a file

  • the pyrevit script will launch the external script with

    output = subprocess.run(["python", path_of_your_script])
    

    and process the output to get the data (or read the file saved by the external script of you went with that route).

Another option: this is not tested, but with the WIP (5.0) version could work since the CPython engine is better (and it is version 3.12): you could try to add at the beginning of your cpython script the instruction

import sys
sys.path.append(path_of_external_sitepackage)

This will add the libraries of your python environment to the one inside pyrevit.
Note that this can bring all sorts of incompatibility problems, but you can just give it a try

1 Like

By the way, you can use MS winforms directly in pyrevit’s cpython (even the current stable 4.8 version), it’s the wpf framework (and by extension the pyrevit forms module) that cannot be used.
You’ll have to build your windows from scratch though… use Excel VBA editor if you want some visual help

I decided to try out subprocess with a regular IronPython script so I can still use pyrevit.forms etc.

Here is the code I added:


import json
import subprocess


ram_model_path = "model path goes here"
path_to_get_tendons = r"lib\get_ram_tendons.py" # path to get_tendons function
tendon_direction = 'direction'
cmd = ['python', path_to_get_tendons, ram_model_path, tendon_direction]

p = subprocess.run(cmd, capture_output=True) # run the subprocess

# Parse the JSON output back into a dictionary
if p.stdout:
    try:
        segments = json.loads(p.stdout.strip())  # Remove any extra whitespace/newlines
    except json.JSONDecodeError as e:
        print("Error decoding JSON:", e)
else:
    print("No output from subprocess.")

print(segments)

and in my get_tendons script I put

import json 
model_path = sys.argv[1]
tendon_direction = sys.argv[2]

def get_ram_tendons(model_path, tendon_direction):

    "function here"

try:
    segments = get_ram_tendons(model_path, tendon_direction)
    # Print the dictionary as a JSON string
    print(json.dumps(segments))
except:
    "Error: Invalid path to RAM model"

I am getting this error once I try to run this in PyRevit

AttributeError: 'module' object has no attribute 'run'

Do you know what’s causing this? When I try to run this similar structure of code in a test script outside of pyrevit it works fine.

Ooops, sorry, I forgot that subprocess.run is a python 3.5+ thing!
For IronPython, that is version 2.7 (or 3.4, but not working very well in pyRevit), you can use subprocess.check_output

Also, if the "python" interpreter you want to call is not in the PATH environment variable, you may need to specify its full path.

Thanks but now I get a new error!

subprocess.CalledProcessError: Command '['python', ram_model_path, tendon_direction]' returned non-zero exit status 2

I’ll have a look into to, but any ideas?

This simply means that the command you launched returned an error.

Some tips:

  • As I mention before, check to see if python is in the PATH (just open a command prompt and launch python to see if it enters the python console);
  • since you specified a relative path for the script, you need to set the cwd parameter for check_output to os.path.dirname(__file__) (that is, the folder containing the pyrevit script)
  • as stated in the subprocess documentation, you can try to show the errors by using stderr=subprocess.STDOUT

Thanks, I’ll give this a go.

As an alternative, is it possible to keep working using the CPython version of my script and obtain the file paths another way? If I create another button in my panel, can I use pyrevit.forms.pick_file to store the file path so it can be used by the CPython script (which is a different pushbutton)?

https://docs.pyrevitlabs.io/reference/pyrevit/coreutils/appdata/

I’ve never played with cpython scripts at all so idk if they can access .net lib, but if it can then this would get you the file dialog.

You can use this instead of subprocess.run with ironpython 2.7

import os
os.system('cmd /c "command"')

Unfortunately a cpython script cannot use the pyrevit.forms library, it was disabled because there were many problems with the old pythonnet (the library that lets you run cpython inside .net).
Now that we updated the library, we should be able to make it compatible, but the last time I tried I hit a wall pretty soon :frowning_face:

As I mention earlier, you can still use winforms directly; this is the first result for a google search with the terms “winforms ironpython”:

From the os.system documentation:

The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function. See the Replacing Older Functions with the subprocess Module section in the subprocess documentation for some helpful recipes.

I meant loading that same dll (Microsoft-windowsAPIcodepack) in the script not accessing thru forms of using cpython.

And thought previous response showed subprocess wasn’t available if using 2.7?

Sorry for the misunderstanding, yes this could be a thing to try!

The thing that is missing is the run function, and as I already explained the check_output function is there and does more or less the same. In fact, they are all convenience functions over the Popen class.