Hi! Is it possible to use virtual environment with python in rhino8?
Not at the moment. The problem is that we are running in a Rhino process so can not load multiple python 3 versions. Supporting separate envs to install pip packages is also a little tricky. For example numpy
uses c-libraries that when they are loaded, they canāt be unloaded. So you canāt really install a specific numpy version in one env and another version in another env and have them both successfully work inside Rhino.
Iām looking at options to improve this continously.
sorry, my question is perhaps a little stupid, but is it possible to indicate at the start of a script to use this or that library folder?
Franck.
The standard way is to add the path where your libraries are to sys.path
In the next build I have added something to make this simpler byt adding # env: path/to/env
to the top of the script.
Are you both referring to python scripting in Rhino or also to the python components in Grasshopper?
@eirannejad is the next build a matter of days or weeks?
Iām asking because having cpython with conda envs in Grasshopper would be a gamechanger for our plugin project.
Another Beta was released yesterday
Thatās what I seemed to have readā¦ but I understood that it was rather complicated to set up, it seemed rather simple to me.
Franck
I had the path to the folder of a virtual environment I made for a script with pandas, at the beginning of a script, I import pandas, but it canāt import it when I launch itā¦ maybe I didnāt understand what you explainā¦
Have you a simple example?
Iām so sorry, but i donāt understand how does it worksā¦ i tried:
"""
NOTE:
- Reference to RhinoCommmon.dll is added by default
- You can specify your script requirements like:
# r: <package-specifier> [, <package-specifier>]
# requirements: <package-specifier> [, <package-specifier>]
For example this line will ask the runtime to install
the listed packages before running the script:
# requirements: pytoml, keras
You can install specific versions of a package
using pip-like package specifiers:
# r: pytoml==0.10.2, keras>=2.6.0
"""
# env: C:\Users\fbaba\Documents\SCRIPT\bdd\env
#! python3
import sys
sys.path.append('C:\\Users\\fbaba\\Documents\\SCRIPT\\bdd\\env')
import rhinoscriptsyntax as rs
import scriptcontext as sc
import System
import System.Collections.Generic
import Rhino
import psycopg2
Psycopg2 is on an virtual environment, i use for a script without rhinoā¦
does rhino install a python executable in rhino installation or does it use the python interpreter already installedā¦
thanks for your helpā¦
Could you please work on the env setting and make the virtual environment possible? or Rhino will miss all AI era. Iāve been using Rhino since 2005 in ZHA. Itās important and please update.
best wishes,
shiqi
@lishiqi We donāt want to miss the AI area obviously, do weā¦
The core of the problem is that you are running mutliple scripts with different envrionments inside the same long-running process (Rhino). Normally when you use python with virtual environments, you are running an independent python process that is tied to that very environment.
We do support one convention in Rhino. You can use the # venv:
directive to provide a name for an separate environment your packages would be installed in (instead of default). This avoids conflicting packages problem but comes with a pretty important caveat. You are still running in the same Rhino process, so although this helps installing package requirements for various scripts in separate environments, if you have numpy loaded from one environment, and a different numpy loaded from another environment, you āmayā run into conflicts.
#! python 3
# venv: <environ-name>
What is the specific path for psycopg2 in this example case?
Is it different then # env: C:\Users\fbaba\Documents\SCRIPT\bdd\env
Hi @eirannejad, thanks for your work for adding py3 capabilities to Rhino. It is surely a long waited feature for the community.
I have gone back and forth at multiple responses here in the forum to grasp what to do and it is still confusing for me and my team how to manage packages installed from different sources.
I suggest writing an official documentation explaining these different usages and how they are/are not the same:
- Using the ārā call
r: numpy
Which for me will install at /.rhinocode/ a version of a package using pip. Understanding how to define a specific version would be useful here too. And what happens if you switch to a different package version? Overwrites it forever at .rhinocode folder?
- Using the āenvā call
env: path/to/env
I tried this and it is not working as expected. First of all can you clarify if you expect the path to the environment root (user/anaconda3/env/myenv) or to the site-packages folder (ā¦env/myenv/Lib/site-packages)?
Another question here is that I often have my packages in a local folder (/user/code/package1) and install them using āpip install -e .ā In which case the package is not copied to /myenv/Lib/site-packages. Do I need then to add ā/user/code/ā to my call?
env: path/to/env
env: user/code
i.e., do I need then to call two environments? That sounds not really the right thing to doā¦
A continuing question is what happens at the .rhinocode folder with all of that? And whatās gonna happen if I mix this with the r call?
- Setting a path at Editor Options
From v8.6 you added an Option function where we can set the env path using the UI. I remain with the same questions regarding which address should be provided (site-package folders or not). And how should we expect that this behaves versus adding # env: path/to/env and adding #r? Also, what happens at .rhinocode in the meanwhile?
Still, what will happen if an address set in the UI is different from the # env: call? Both get called?
- Using venv
venv: myenv
This is new for me, should we only provide the anaconda3 environment name here? Would be interesting to understand if locally installed packages āpip install -e .ā get included too and what happens at .rhinocode folder/ how it crashed with all the other options above.
- Using sys.path.add
In the middle of all these different calls, I am not sure whether we should or should not use this method? Should this point to the environment root or the site-package folder?
Sorry for the long post but I hope this also help others with similar questions.
Ricardo -
I am also trying to write a guide on this. I hope early next week to have a draft. But, letās take a look at each of these issues you take up in this thread as a way to work through each. it will help me get it in the guide.
This is not the complete guide, just some notes from it.
The conda
virtual environment situation is not easily handled yet. So I am going to skip that for now.
Introduction:
There are 4 main sources of Python modules that may be installed or loaded into Python 3.
- Built-in Modules - Built into Python 3, this also includes our Rhino specific libraries such as RhinoscriptSyntax and RhinoCommon.
- Local Modules - Created from other user .py files using
def
- Packages on PyPI website - 300,000 Python Modules
- Downloaded Packages - Downloaded libraries and unzipped modules into folders.
Using PIP: - Packages on Pypi
Using r:
or requirements:
can be set at the start of a script.
It is recommended that multiple packages are listed on a single line, as the installer will then be able to combine shared packages:
#r: numpy, scipy
Dependency Specifiers can also be used:
#r: numpy >= 1.3, scipy == 3.4.*
I have not found a simple guide on dependency specifiers yet.
Local Modules and Downloaded Modules:
Both user created local modules and downloaded modules must be stored in a folder or sub-folder that can be found by the rhino.python sys environment.
The sys.path
is set at a few different levels:
- The default rhino.python sys.path
- The local folder the current python file is stored in
- Any folders added in the Tools > Options > Python3 > Module search paths
- A path set in the script by
# env: \\xxx\xxx\x
- Folders added within the script by:
sys.path.append('C:\\Users\\fbaba\\Documents\\SCRIPT\\bdd\\env')
The built in default location for modules and library folders on Windows is:
%HOMEPATH%\.rhinocode\py39-rh8\\Lib\site-packages\
For Mac:
~/.rhinocode/py39-rh8
All of these simply add to the search path. To print the current path in the middle of a script use this:
import sys
paths = sys.path
for path in paths:
print(path)
hello,
no it is not different, in fact I a made a python script to save project datas, outside of rhino, so i work with virtual environement for a tkinter application, this app use pandas, psycopg2, customtkinterā¦
if i want to make a script in rhino, to acces the projects datas i easier to use the same virtual environementā¦
Virtual environments inside of Rhino are very different from the way they are setup by conda or other virtual environment (venv) managers that you are used to with your python 3 workflows. Take a look at this swimlane chart for example:
Top:
Running multiple python scripts using python.exe
. Note the gray boxes marked as P1 and P2. Each python execution a separate process, and independent venv with no conflicts.
Bottom:
Running multiple python scripts in rhino.exe
- Note everything is in the same gray box. They all share the same process and memory so multiple venvs could potentially conflict.
This is why we are not supporting python 3 virtual environments inside of Rhino yet. We use independent folders with some python packages (# venv
) so scripts donāt have to constantly override each others packages. For example script 1 can install numpy==1
in their own folder # venv: script-one
, and script 2 can install numpy==2
in their own # venv: script-two
But if you run both scripts in the same rhino, numpy
1 and 2 āmightā conflict during load or running the two scripts.
Tkinter also does not work inside of Rhino yet as it needs its own application instance with event loop that is different from Rhino.
Hi Ehsan,
Thank you for the detailed explanation and the swimlane charts illustrating the differences between running Python scripts in standard environments and within Rhino. Your clarification on why Rhino currently handles Python virtual environments (venvs) in this unique way is insightful.
I understand the challenges of maintaining a stable platform for users at all levels and the potential for conflicts when multiple venvs are used within the same Rhino instance. However, as an advanced user who raises this question, I often find myself needing more control over the development environment, including the ability to manage dependencies through pip
and virtual environments. This control is especially crucial when working with complex projects that require specific versions of libraries or when integrating external Python tools.
I believe that while the current system ensures stability, it may limit advanced users who are accustomed to a more flexible Python development workflow. Perhaps a compromise could be introducing an advanced mode or an option for users to opt-in for more control over their environments. This way, users who are comfortable managing potential conflicts could take advantage of Rhinoās full capabilities alongside their preferred Python development tools.
I am looking forward to any developments in this area and would be happy to provide more feedback or participate in a beta testing phase if that would be helpful.
Best regards,
Shiqi
You can use an independent deployment of python matching Rhino python version (3.9.10 as of writing this post) to create environments and install any combination of packages in those environments. Then you can add the path of the Libs\site-packages
in that environment to your scripts in Rhino:
# env: /path/to/venv/Libs/site-packages
or add the path directly to sys.path
The problem however remains that if you are using multiple virtual environments in the āsame Rhino processā there is always a potential for runtime conflicts.