pyRevit
pyRevit copied to clipboard
CPython interpreter not working
I am trying a execute a very simple script as a test in preparation to using a CPython library in my script:
#! python3
import Autodesk.Revit.DB as DB
from Autodesk.Revit.UI import TaskDialog
from pyrevit import revit
doc = __revit__.ActiveUIDocument.Document
td = TaskDialog.Show("testing", doc.PathName)
The script works fine when I remove the first line (#! python3), but crashes with this error if I leave it:
CPython Traceback:
KeyNotFoundException : KeyError
at IronPython.Runtime.PythonDictionary.GetItem(Object key)
at IronPython.Runtime.PythonDictionary.get_Item(Object[] key)
pyRevitLabs.PythonNet
[' File "<string>", line 5, in <module>\n', ' File "C:\\Program Files\\pyRevit-Master\\pyrevitlib\\pyrevit\\revit\\__init__.py", line 23, in <module>\n from pyrevit.revit import ui\n', ' File "C:\\Program Files\\pyRevit-Master\\pyrevitlib\\pyrevit\\revit\\ui.py", line 12, in <module>\n from pyrevit.runtime import types\n', ' File "C:\\Program Files\\pyRevit-Master\\pyrevitlib\\pyrevit\\runtime\\__init__.py", line 20, in <module>\n from pyrevit.userconfig import user_config\n', ' File "C:\\Program Files\\pyRevit-Master\\pyrevitlib\\pyrevit\\userconfig.py", line 50, in <module>\n from pyrevit.versionmgr import upgrade\n', ' File "C:\\Program Files\\pyRevit-Master\\pyrevitlib\\pyrevit\\versionmgr\\__init__.py", line 18, in <module>\n from pyrevit.coreutils import git\n', ' File "C:\\Program Files\\pyRevit-Master\\pyrevitlib\\pyrevit\\coreutils\\git.py", line 29, in <module>\n mlogger.debug(\'Loading dll: %s\', LIBGIT_DLL)\n', ' File "logging\\__init__.py", line 1421, in debug\n', ' File "C:\\Program Files\\pyRevit-Master\\pyrevitlib\\pyrevit\\coreutils\\logger.py", line 148, in isEnabledFor\n envvars.get_pyrevit_env_var(envvars.FILELOGGING_ENVVAR)\n', ' File "C:\\Program Files\\pyRevit-Master\\pyrevitlib\\pyrevit\\coreutils\\envvars.py", line 104, in get_pyrevit_env_var\n return data_dict[param_name
Revit v2020.2.9 PyRevit v2.4.12 Windows 10
Same issue here with Revit 2022.1 and CPython
UPDATE It seems isolated to CPython 3.8.5. I just switched over to 3.7.8 and importing pyRevit works fine. I also have this issue in Revit 2023.1. I tested the "Test CPython Command" in the pyRevitDev tab and it prints everything right up until the "import pyRevit" line of code and throws the same error
Unfortunately, I can't confirm that. Both versions of CPython 3.8.5 and 3.7.8 result in the same error, when I try to import pyrevit.
I'm using Revit 2023.1.1 and pyrevit 4.8.12
Now following this thread as I'm also getting this exception using CPython 3.8.5, R2022.2 and ((shakes fist at screen)) not able to import pyrevit python module
I've investigated the problem a bit more and i've found a workaround to use at least environment variables:
#! python3
import sys
print(sys.version)
###### WORKING EXAMPLE / WORKAROUND TO GET ENVIRONMENTAL VARIABLES WORKING
from pyrevit.coreutils import envvars
env_dict = envvars.get_pyrevit_env_vars() # env_dict is of type IronPython.Runtime.PythonDictionary
# Iterating this dict (IronPython.Runtime.PythonDictionary) works and print all environment variables and their values
for k, v in env_dict.iteritems():
print(k, v)
# Getting the value directly works after getting the complete env_dict into the script
my_env_value = env_dict.get('MY_ENV_VARIABLE')
print(f"MY_ENV_VARIABLE: {my_env_value}")
###### NOT WORKING EXAMPLE
print(envvars.get_pyrevit_env_var('MY_ENV_VARIABLE')) ### --> this fails with following error messages:
#KeyNotFoundException : KeyError
#bei IronPython.Runtime.PythonDictionary.GetItem(Object key)
#bei IronPython.Runtime.PythonDictionary.get_Item(Object[] key)
The Problem is caused in line 104 in envvars.py file:
def get_pyrevit_env_var(param_name):
"""Get value of a parameter shared between all scripts.
Args:
param_name (str): name of environment variable
Returns:
object: any object stored as the environment variable value
"""
# This function returns None if it can not find the parameter.
# Thus value of None should not be used for params
data_dict = AppDomain.CurrentDomain.GetData(ENV_VAR_DICT_NAME)
if data_dict:
try:
return data_dict[param_name] ## ANY NEW LINE HERE, EVEN A print "test" CAUSES AN ERROR?
except KeyError: ## KeyNotFoundException will be raised from Ironpython, I dont know if this will be mapped to a python3 KeyError?
return None
else:
return None
Hi, I encountered this a while ago as reported in this old issue while trying to make pyrevitlib CPyhon compatible.
I couldn't get what's going on in those lines and I gave up.
Could it be that GetData
returns a data structure not entierly compatible with python?
maybe instead of using the try/except
, a data_dict.get(param_name)
would work... I'll test it and get back to you
I've tested 'data_dict.get(param_name)' or even a simple print("foo bar bla") without success.
I think it is related to a logging issue.
I don't know why this works, but I made it work by DRYing the code (that is, calling get_pyrevit_env_vars
in the other envvars
functions):
def get_pyrevit_env_vars():
"""Get the root dictionary, holding all environment variables."""
return AppDomain.CurrentDomain.GetData(ENV_VAR_DICT_NAME)
def get_pyrevit_env_var(param_name):
"""Get value of a parameter shared between all scripts.
Args:
param_name (str): name of environment variable
Returns:
object: any object stored as the environment variable value
"""
# This function returns None if it can not find the parameter.
# Thus value of None should not be used for params
data_dict = get_pyrevit_env_vars()
return data_dict.get(param_name) if data_dict else None
def set_pyrevit_env_var(param_name, param_value):
"""Set value of a parameter shared between all scripts.
Args:
param_name (str): name of environment variable
param_value (object): any python object
"""
# Get function returns None if it can not find the parameter.
# Thus value of None should not be used for params
data_dict = get_pyrevit_env_vars() or {}
data_dict[param_name] = param_value
AppDomain.CurrentDomain.SetData(ENV_VAR_DICT_NAME, data_dict)
Of course this doesn't completely solves the OP issue, since the execution stumbles on another exception, but at least we ruled the envvars out.
Can you try it and confirm that works for you? If so, I'll do a PR ASAP
@vmarquar have you got the chance to check if my patch works for you?
@eirannejad @jmcouffin
I suppose that all those CPython issues (here and on the forum) should be adressed by first updating the pythonnet libary. I could take a stab at this, but I need some directions. I see that the python.net library is a sumbodule in dev/modules, should it be enough to upgrade that sumbodule to the 3.0.1 release commit and then rebuild everything to see if it still works?
I see that now pythonnet supports up to python3.11, so another thing to do is to add the whenever needed. Is there a list of those places or should I do a global search on the codebase?
I would not be the one to guide you @sanzoghenzo It is way above my league If @eirannejad gets a chance...
@vmarquar have you got the chance to check if my patch works for you?
Yes, i've just tested it and your workaround works (at least for the envvars import) 🥳
Testing code:
- edit the
envvars.py
file according to sanzoghenzo's comment - run follwowing code as revit extension
#! python3
import sys
print("running test - github issue #1749")
print(sys.version) #prints on my machine: 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)]
# TESTING sanzoghenzo workaround (edit envvars.py file)
from pyrevit.coreutils import envvars
envvars.set_pyrevit_env_var("testkey", "mytestvalue")
mytestvalue = envvars.get_pyrevit_env_var("testkey")
print(mytestvalue)
all_env_vars = envvars.get_pyrevit_env_vars()
print(all_env_vars) # =IronPython.Runtime.PythonDictionary
for k in all_env_vars:
print(k)
print("finished script - everything ok!")
But as you mentioned importing pyrevit or some of its submodules doesn't work yet:
#from pyrevit.coreutils import envvars #--> Works (But this has worked before as well I think...)
from pyrevit import script # ---> Fails: TypeError : No method matches given arguments for CompileCSharp: ()
Hi Guys,
I'm facing this exact same issue. Is there any timeline on the fix? Is there a way I can help?
Thanks, Julio
Hi @julillosamaral
I submitted the fix for the envvars module a few hours ago, but it might take a while for it to be published in an official release.
For the bigger issue of cpython compatibility, I can't promise any ETA because I just started analyzing pyrevitlabs and pythonnet c# code.
Some of my findings (@eirannejad correct me if I'm wrong):
- now pythonnet can be compiled once for all the python versions, it's just a matter of setting the
Runtime.PythonDLL
property orPYTHONNET_PYDLL
environment variable to the path of the python3xx.dll, so the build process must be changed to reflect that - There is still the need to maintain a fork of the library to expose some internal methods used by pyrevit; maybe in the future the parts of pyrevit's code that access those internal methods can be moved to the upstream pythonnet repo for everyone to enjoy (I only analyze two methods/usages, not sure if this can be done yet)
- after that, there will be the need to adapt the code to prevent troubles with pythonnet 3 breaking changes and deprecations.
- since pythonnet supports python up to version 3.11, we can add all the supported engines to pyrevit. I still haven't looked at how this should be done other than the pyRevitFile
Little update: after many hour of searching I discovered that Runtime.LoadModule
was removed in favor of the new PyModule.Import
method (Already filled an issue in the pythonnet github to ask to update the documentation).
I should have found a way to convert the search paths python list into a .NET list without having to access the PyList_GetItem directly;
I'll be away for the weekend, but I really appreciate if @eirannejad could advise me on how to do proper testing for when I get back. How can I run the visual studio project in revit? it seems that there are no debug/running config, is it on purpose?
This issue is unfortunately still present in: Revit 2023.1 pyRevit 4.8.13.23182 on engine CPython 3.8.5
I don't know why this works, but I made it work by DRYing the code (that is, calling
get_pyrevit_env_vars
in the otherenvvars
functions):def get_pyrevit_env_vars(): """Get the root dictionary, holding all environment variables.""" return AppDomain.CurrentDomain.GetData(ENV_VAR_DICT_NAME) def get_pyrevit_env_var(param_name): """Get value of a parameter shared between all scripts. Args: param_name (str): name of environment variable Returns: object: any object stored as the environment variable value """ # This function returns None if it can not find the parameter. # Thus value of None should not be used for params data_dict = get_pyrevit_env_vars() return data_dict.get(param_name) if data_dict else None def set_pyrevit_env_var(param_name, param_value): """Set value of a parameter shared between all scripts. Args: param_name (str): name of environment variable param_value (object): any python object """ # Get function returns None if it can not find the parameter. # Thus value of None should not be used for params data_dict = get_pyrevit_env_vars() or {} data_dict[param_name] = param_value AppDomain.CurrentDomain.SetData(ENV_VAR_DICT_NAME, data_dict)
Of course this doesn't completely solves the OP issue, since the execution stumbles on another exception, but at least we ruled the envvars out.
Can you try it and confirm that works for you? If so, I'll do a PR ASAP
I tried this, but I'm not sure if it works or not, because different error showed up immediately. So probably the issue is much deeper..
This issue is unfortunately still present in: Revit 2023.1 pyRevit 4.8.13.23182 on engine CPython 3.8.5
Yes, the fix is on the development branch, so you either use a WIP release or wait for the next release.
I tried this, but I'm not sure if it works or not, because different error showed up immediately. So probably the issue is much deeper..
That's exactly what I stated under the code 😉
I'm still waiting/hoping for @eirannejad (btw, I hope you are OK!) to explain how to test/debug the addon from visual studio, then I can proceed with the pythonnet upgrade and start to resolve this issues...
Yes, the fix is on the development branch, so you either use a WIP release or wait for the next release.
Perfect. Thank you 👍
I faced same issue and here is what I get with C Python 3.7.8 ( I will try 3.8.5 next but expect similar issue)
CPython Traceback:
TypeError : No method matches given arguments for CompileCSharp: ()
File "C:\Users\user\OneDrive\Documents\Myc\pyrevit_custom_buttons\MyExtensions\MyExtensions.extension\Myc.tab\Myc.panel\circuits_info.pushbutton\script.py", line 16, in
pyRevitLabs.PythonNet at Python.Runtime.Runtime.CheckExceptionOccurred() at Python.Runtime.PyScope.Exec(String code, IntPtr _globals, IntPtr _locals) at Python.Runtime.PyScope.Exec(String code, PyDict locals) at PyRevitLabs.PyRevit.Runtime.CPythonEngine.Execute(ScriptRuntime& runtime)