Wondering how to share code between 2 pushbuttons?

We need to share code between 2 pyrevit pushbuttons.
How is this achieved in pyrRevit?

what I have tried:

  • search the web
  • ask chat gpt
  • the following:

|— button1/
|— script.py
|— button2
|— __init__.py
|__ test.py


def test():


from common.test import test

yields (of course)
ImportError: No module named formx_common.test


if i understand the question correctly , I reckon this is what you are looking for
Bundle lib
put the repeating code in a different class in the lib folder and then you can call the methods easily as needed

@Oded_F ,

you can creat a lib folder f.e. snippets. here the example from EF-Tools

so all functions are stored there:

Indeed, this is what we are looking for.
(Basically, rename common to test.)
But I am not able to import it.

in script.py:
import test
ImportError: No module named test

import lib.test
ImportError: No module named lib.test

1 Like

@Oded_F ,

ok i tested folder structure is the key

# 🛒get module
from Test import _test

# 🥕🧅🥑 snoop module


my module is structured like this

Thanks for testing, I assume that you were able to get it work, but I do not understand yet :).

Not taken for granted!

Can you please share your directory structure, so I can try and reconstruct?

@Oded_F ,

i followed just the documentation from @revitislife
i just put my lib there… and set the bundle also

than it runs.

Is there a bundle file needed?

I can not see a trace of this in:

Is there a documentation somewhere?
I can not see any at:

If you resolve this, I will create a git repo in your honor with a working implementation sir!


try adding the path to lib in your script that will import the functions.

from sys import path

can also use relative pathing

script_path = script.get_script_path()
common_root = os.path.dirname(os.path.dirname(os.path.dirname(script_path))) # this goes up the directory tree a couple levels
lib_path = os.path.join(common_root, 'lib', 'libfolder') # points to a subfolder in lib

Don’t use from common.test import test

from {library_file_name} import {function_name}

probably need to rename the function name to keep if from getting confusing, since you would be importing test from test.

I’ve also found that all changes to library files require reloading pyrevit. script.py files for the button scripts do not require a reload, just save the file, but lib require it.

1 Like

Do you not need to add the library folder to path in each script to use? I havent been adding lib to my bundle.yaml so maybe this explains it… thought the bundle.yaml was just for the UI order

1 Like

I confirm that there’s no need to add the lib folder(s) to the bundle, nor add it to the sys.path since they are automatically added by pyrevit.

here’s my structure, as you can see my scripts imports from the lib folder in box the extension root folder and the tab one.

Please don’t. :wink:

Chat GPT has little to no knowledge about the inner workings of pyRevit, so it is pretty useless for this kind of things

@Oded_F - what @sanzoghenzo showed is exactly how I would recommend - the lib folder lives in the main root extension folder
Also couldn’t agree more regarding pyrevit and chatgpt - it has very little knowledge of pyrevit as well as Revit API.
This is how I have my lib folder setup

Depends. Somebody very familiar with the Revit API and knows C# or python can quickly produce some pretty advanced scripts. You have to point it in the correct direction and explain exactly what you are looking for, but if you can’t identify issues just looking at the code in the browser, then you are going to waste a ton of time spinning in circles.

I found feeding it a script that is at least vaguely similar to what you are looking for and telling it what you want to modify it to do is better than asking it to create something from scratch. once you know how to ask it for what you want you can produce code absurdly quickly, but it’s a double edged sword if you treat it like your personal software developer.

YOU are the software developer. It’s just a text generator that produces code when you ask it the right way.

I have my lib folder under the tab folder, not the extension folder. Could that be the issue?

As you can see in my previuos post, I too have a lib folder in the SWS.tab, and it works ok.

It is really easy to check what’s loaded by pyrevit before a script is run, just add these two lines:

import sys
1 Like