pyRevit cannot load .pyc on Revit 2020

First of all, many thanks for the team because of creating pyRevit

I try to apply pyc file to all the script.py & library for my team. The pyc folder will be stored on the server and can be call by other people to run selected tools. This worked well for Revit 2019, 2021, 2022, 2023 & 2024 but failed with 2020. All of them have the same pyc library.

This worked perfect on revit 2023

But failed in 2020

This said that load the pyc successfully but can not call the module
They use the same pyc file

How can we make this work on Revit 2020
Could you please review this and give me some advice?

Hi @ngkhtien, what do you mean by “apply pyc file”? Ironpython cannot use compiled cpython files, and even if it was able to do it, it’s not a great idea to distribute compiled python script to a team that uses different versions of revit and ironpython/cpython engines.

What I did at my company was to create a git repository and instruct my colleagues to clone it and pull it whenever the code is updated/added. This will solve many problems with shared folders (be them on a local server or cloud storage).

Thanks for your response.

Our pyc use iron python inside, follow the instruction from eirannejad here:

Regarding your solution, I thought about this before but my boss doesn’t want to share our source code with other teams except running tools. That is why I try to compile all the current source code into pyc.
All members of my company use different Revit but the same pyRevit version.

Here is my current code for running a tool

 # create pyc user folder
    main_path = r"\\srvprd1\Atlas\Digital Shared\Automation Tool\Temp\User Temp"
    # main_path = r"C:\Users\quoch\Desktop\PYC_USER"
    pyc_user_folder = os.path.join(main_path, date)
    if os.path.exists(pyc_user_folder):
        pass
    else:
        os.mkdir(pyc_user_folder)

    # add user pyc folder to sys
    sys.path.append(pyc_user_folder)

    # get dev pyc folder
    OSF(1, source_path)
    pyc_dev_folder = r"\\10.179.120.2\pyatlas\Temp\Dev Temp\main_script"
    # pyc_dev_folder = r"C:\Users\quoch\Desktop\PYC"
    current_pyc_devLst = os.listdir(pyc_dev_folder)

    # copy pyc from dev to user folder
    if "Shortcut_General Shortcut" not in source_path and "Shortcut_Local Shortcut" not in source_path:
        tool_name = ToolData(source_path)
        if tool_name is None:
            print("data file has a wrong format")
        else:
            pyc_dev_path = None
            target_path = None
            for current_pyc_dev in current_pyc_devLst:
                if tool_name in current_pyc_dev:
                    pyc_dev_path = os.path.join(pyc_dev_folder, current_pyc_dev)
                    target_path = os.path.join(pyc_user_folder, current_pyc_dev)

            if pyc_dev_path and target_path:
                if os.path.exists(target_path):
                    pass
                else:
                    shutil.copyfile(pyc_dev_path, target_path)
                clr.AddReferenceToFileAndPath(target_path)
                import main_script
            else:
                print("Failed to get pyc file")
    else:
        print("This is a shortcut")

Here is my current code for loading library

    pyc_lib_load = False
    # get dev pyc folder
    pyc_dev_folder = r"\\srvprd1\Atlas\Digital Shared\Automation Tool\Temp\Dev Library"
    current_pyc_devLst = os.listdir(pyc_dev_folder)

    # get user pyc folder
    main_path = r"\\srvprd1\Atlas\Digital Shared\Automation Tool\Temp\User Temp Library"
    pyc_user_folder = os.path.join(main_path, date)
    try:
        os.mkdir(pyc_user_folder)
    except:
        pass
    sys.path.append(pyc_user_folder)

    pyc_dev_path = None
    target_path = None
    for module_name in module_nameLst:
        for current_pyc_dev in current_pyc_devLst:
            if module_name in current_pyc_dev:
                pyc_dev_path = os.path.join(pyc_dev_folder, current_pyc_dev)
                target_path = os.path.join(pyc_user_folder, current_pyc_dev)
                break

        if pyc_dev_path and target_path:
            try:
                shutil.copyfile(pyc_dev_path, target_path)
            except:
                pass
            clr.AddReferenceToFileAndPath(target_path)
            pyc_lib_load = True
        # if pyc_lib_load:
        #     print(module_name + ": load Successful")
        # else:
        #     print(module_name + ": load Failed")
    if revit_version == 2020:
        pyc_lib_load = False

I put our project on GitHub and shared it with colleagues who have a responsibility to maintain it. A copy will be put on the server and all other machines will get a link to this for the custom tab. They only use a simple script for running a selected pyc.
These can work well on 200+ machines with Revit version 2019, 2021 - 2024 but not work on 2020.

I’m new in this field, just 6 months into programming so don’t have any experience. If you have any solution to hide the source code or make a pyc run on Revit 2020, please advice me. Many thanks.

Hi @ngkhtien, sorry for the wrong info, I didn’t know you can compile ironpython code (my google-fu is getting worse and worse!).

it’s not the pyRevit version per se that counts, but the selected ironpython engine in the settings. It should be exactly the same used when compiling the pyc files.

Other than that, I’m sorry I can’t help you, I don’t obfuscate my code.

I suggest you to tell your boss we’re not in the 2000 anymore :rofl: you don’t do money with code but providing services on top of it :wink:

Thanks for your reply, that is a good point about dealing with my boss