Windows - Creating a Poetry Virtual Environment for LibreOffice


LibreOffice on Windows is shipped with its own embedded Python. Unfortunately, this Python is not compatible with the Python Poetry needs to use.

To work around this, we need to create a virtual environment with a compatible Python version. This virtual environment will need to be able to be used by both Poetry and LibreOffice. This is not straightforward, as LibreOffice does not support virtual environments unless it is configured in a specific way.

If you only need pip and not Poetry, then see Windows - Manually Creating a Virtual Environment to create a virtual environment.

This guide will show you how to create a virtual environment with Poetry and pyenv.

The reason pyenv is used is because it provides a way to install a compatible Python version on Windows that matches the version of Python shipped with LibreOffice.

See Configure a Poetry environment for poetry installation instructions.


This guide assumes you have already installed LibreOffice.

Anywhere you see <username> it needs to be replaced with your Windows username.

Installing pyenv

To install pyenv follow the instructions on the pyenv GitHub page.

How to use pyenv however, is out of the scope of this guide, so only limited instructions will be provided.

Installing a python version

First, we will need to get the version of Python that LibreOffice uses.

&"C:\Program Files\LibreOffice\program\python.exe" --version

This will output something like: 3.8.16

List the available versions of Python that can be installed with pyenv. Limit the output to only versions that match the major and minor version of the Python version that LibreOffice uses.

pyenv install -l | findstr 3.8

At the time of writing this guide pyenv does not have a 3.8.16 version of Python but it does have a 3.8.10 version. As long and the major and minor versions match, it will be fine. So any 3.8.x version will work.

Install the 3.8.10 version of Python:

pyenv install 3.8.10

pyenv will download and install the Python version. The installation path will be something like: C:\Users\<username>\.pyenv\pyenv-win\versions\3.8.10

Creating a virtual environment

Now that we have a compatible version of Python installed, we can create a virtual environment. For the purpose of this guide, we will create a virtual environment in the D:\tmp\project directory.

cd D:\tmp\project

Create the virtual environment with the 3.8.10 version of Python:

&"C:\Users\<username>\.pyenv\pyenv-win\versions\3.8.10\python.exe" -m venv --without-pip .venv


The --without-pip option is used because we will be using Poetry to manage the packages. And pip is not needed. If you need pip for some reason then you can omit the --without-pip option.

Activate the virtual environment:


Check the version of Python:

(.venv) PS D:\tmp\project> python --version
Python 3.8.10

Initialize poetry project

Use poetry to initialize a project. We will add packages later as there are some additional steps that need to be done.

cd D:\tmp\project
poetry init


This command will guide you through creating your pyproject.toml config.

Package name [project]:
Version [0.1.0]:
Description []:  My fantastic project
Author [Secret Name <secret@name.nowhere>, n to skip]:
License []:  MIT
Compatible Python versions [^3.9]:  ^3.8

Would you like to define your main dependencies interactively? (yes/no) [yes] n
Would you like to define your development dependencies interactively? (yes/no) [yes] n

The generated pyproject.toml file will look something like:

name = "project"
version = "0.1.0"
description = "My fantastic project"
authors = ["Secret Name <secret@name.nowhere>"]
license = "MIT"
readme = ""

python = "^3.8"

requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Install OOOENV

oooenv is a Python package that allows you to auto configure a virtual environment to be used by LibreOffice.

Install oooenv in the virtual environment:

poetry add oooenv --group=dev


The --group=dev option is used because we only need oooenv for development purposes. This option instructs Poetry to only add oooenv to the dev-dependencies section of the pyproject.toml file.

Do a version check to make sure it is installed:

(.venv) PS D:\tmp\project> oooenv --version

Toggle Environment

Now that we have oooenv installed, we can toggle the virtual environment to be used by LibreOffice.

oooenv env -t


Saved cfg
Saved cfg
Set to UNO Environment

Now the environment is configured to be used by LibreOffice.

(.venv) PS D:\tmp\project> python --version
Python 3.8.16

Run python in the virtual environment:

(.venv) PS D:\tmp\project> python
Python 3.8.16 (default, Apr 28 2023, 02:01:33) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import uno

Toggle Environment:

When you want to switch back and forth to the original environment, run:

(.venv) PS D:\tmp\project> oooenv env -t
Set to Original Environment

Install additional packages using poetry

Now that we have a virtual environment that can be used by LibreOffice, we can install additional packages using poetry.

Make sure we are not in UNO Environment:

(.venv) PS D:\tmp\project> oooenv env -u
NOT a UNO Environment
poetry add ooo-dev-tools


Using version ^0.11.6 for ooo-dev-tools

Updating dependencies
Resolving dependencies... (0.9s)

Package operations: 6 installs, 0 updates, 0 removals

• Installing types-uno-script (0.1.1)
• Installing types-unopy (1.2.3)
• Installing typing-extensions (4.6.3)
• Installing lxml (4.9.2)
• Installing ooouno (2.1.2)
• Installing ooo-dev-tools (0.11.6)

Writing lock file

Now we can see in our pyproject.toml file that the ooo-dev-tools (OooDev) package has been added:

python = "^3.8"
ooo-dev-tools = "^0.11.6"

While we are in the original environment, we do not have access to LibreOffice and UNO. So we will toggle again.

(.venv) PS D:\tmp\project> oooenv env -t
Set to UNO Environment

Now we can take advantage of OooDev.

>>> import uno
>>> from ooodev.loader.lo import Lo
>>> from ooodev.calc import CalcDoc
>>> def say_hello(cell_name):
...     doc = CalcDoc.from_current_doc()
...     sheet = doc.sheets[0]
...     sheet[cell_name].value="Hello World!"
>>> _ = Lo.load_office(Lo.ConnectSocket())
>>> doc = CalcDoc.create_doc(visible=True)
>>> say_hello("A1")
>>> doc.close()
>>> Lo.close_office()

The result can be seen in Fig. 1220

Calc Hello World

Fig. 1220 Calc Hello World