I am trying to install packages to a virtual environment, and then uninstall them when I made a mistake.
In the script editor, I have found the Open Python 3 Shell. When running python there, it doesn’t have numpy installed, so I tried looking for a venv activate file, but the site-envs seems to just be a folder.
From what I gather, there aren’t really virtual environments, just directories with names on them.
The issue I have is managing the env: directive at the top of a python script. This seems to be persistent, or is corrupting something. I’m not sure what about running a script is causing the issue, but it essentially is:
A local project folder that has scripts and calls a module in that folder.
Open one of those scripts in the Script editor, run it.
this works fine. I suspect because it is using the file/script directory (maybe relative path context?)
Copy that same files code, and put in the script editor directly to run.
to compensate for the local module, I add the path of the file i copied into env: path/to/file
this causes permanent crashing, until the editor.json is deleted
You are correct. The subfolders under site-envs are not virtual environments. It is key to know that you are running in a single long-running process. So one a version of numpy libraries are loaded, loading another version causes conflicts.
The site-env folders are designed to allow multiple package versions and their dependencies to be installed separately from each other. Each folder can contain a combination of packages required by one of your scripts. But you still need be aware of multiple versions of the same library loaded in Rhino:
Imagine this scenario:
file script_a.py requires numpy version 1
file script_b.py requires pytorch version 2 which is dependent on numpy version 2
On a clean Rhino, running script_a installs and loads numpy v1
On a clean Rhino, running script_b installs and loads pytorch + numpy v2
Conflict:: Currently running script_b right after script_a might cause conflicts since numpy v1 is already loaded. So when pip wants to uninstall numpy v1 to install numpy v2 on windows it fails to delete numpy’s native libraries that are loaded in Rhino memory as these files are locked.
Workaround: Specify a venv: some-env-name at the top of your scripts. This will create a subfolder under site-env for this script and installs the packages there. And since there is no numpy v1 is installed in this folder there is no install conflict.
Now all the packages required for the two scripts are installed. You still need to run each script in a fresh Rhino instance since you need to make sure two version of numpy are not loaded at the same time. But the separate environments cache the necessary packages so they don’t need to get installed-uninstalled every time you are running multiple packages with different package requirements.
I would advise against manually adding the paths to these folders to your script. Just use the venv: specifier. Note that env: is different from venv:
Python Shell
When using the python shipped with Rhino, in the python shell, and manually adding/removing packages, you need to specify the --target which is the subfolder inside site-envs directory. The prompt on the shell has a note for this. See highlighted text below:
It was not script_a then script_b, it was script_a twice in a row.
I think the terminal is confusing for me for a few reasons;
there is no site-packages under libs folder.
When running python.exe, I would expect the modules installed to be part of it. I guess this has something to do with this sort of runtime loading.
a. but typically executing python.exe and in that environment I should import numpy, when it is part of the pip-installed modules
b. since this is framed as ‘a single long-running process’, I would expect it to have all installed modules available
So, how could I start the python instance in the terminal, where it is pulling the modules from the folders?
Some unsolicited and uninformed , respectfully, thoughts/questions on, ‘why not do…’:
Maybe loaded modules can be tracked with modulefinder and/or sys dictionary, then 1. Raise a warning, but use an existing module instance instead of installing to a new ‘pseudo’ environment or 2. raise an exception when there are requirements set at the script level with conflicting module versions (i.e. numpy 1.12 is already loaded, but user puts # r: numpy==1.13 in their own script.
I just got this documented here with some sketches/images to explain. Take a look and see if it makes sense. I am all for making improvements and getting the package conflict issues resolved. You definitely should have a site-packages directory as pip and some other utilities are installed there. It is under ~/.rhinocode/py38-rh8/lib/python3.9/site-packages on macOS and %USERPROFILE%\.rhinocode\py38-rh8\lib\site-packages on Windows:
As for the guide, which is really nice;
The first paragraph of this section Rhino - Python Package Environments that threw me off, since I didn’t realize it wasn’t talking about Rhino yet. I was looking for site-packages in the folder where the pseudo virtual environment was.
Maybe just rephrasing to start with:
Unlike the implementation used in Rhino, users may be familiar with tools like pipenv and venv environment managers for Python, which normally solve this problem by creating multiple Virtual Environments
Python 3 will create new folder site-envs/my-pytorch-tools-<unique-id> to install pytorch v2.4.1 in that environment. <unique-id> is automatically assigned to the environment to avoid conflicts:
It’s not obvious to me when a new environment is created, and when a unique-id is appended. If I use # venv: just-for-me , it makes a folder like ./just-for-me-0x2340sdfjl. So when I run it again, or make a new script, or open rhino again, and still have # venv: just-for-me, does it use ./just-for-me-0x2340sdfjl or makes a new one with a unique id ./just-for-me-sdl8280jl . How would I know this, and why would the unique id get appended at all if it just references the name I use to begin with.
In case any install errors occured, please run Tools > Advanced > Reset Python 3 (CPython) Runtime to reset the complete runtime and install a fresh deployment of Python 3 with clean site-packages and site-envs directories.
Not sure if it’s the explanation or I have a different issue, but often this reset doesn’t work, I just get an error that the environment is corrupted, and only way to solve it is restarting Rhino, not just resetting python.
Script specifying just-for-me always uses the just-for-me-<unique-id> that was created for it on the first run. This way the required packages for this script do not need to be installed every time
Yes if there is installation errors, the environment is marked as invalid and Rhino needs to be restarted. Tools > Advanced > Reset Python 3 (CPython) resets the complete python runtime including all the various environments and everything else in the folder (still needs Rhino restart)