Hi, I'd like to ask how exactly does Pulumi use vi...
# python
p
Hi, I'd like to ask how exactly does Pulumi use virtual env specified under
runtime.virtualenv
in the project file. Especially does it switch to the virtual env prior to running the Pulumi program? As it seems it does not. Here's the context. I'm using Ubuntu 22.04 which uses Python 3.10 by default. I also installed Python 3.11 (from PPA) because that's the target runtime I use on AWS. I'm provisioning couple of Lambda functions and in the Pulumi program, I use
local.Command
from Pulumi Command provider to prepare the distribution package for the Lambdas. The command installs the dependencies using
pip
into a directory containing the handler and then uses the directory in
pulumi.FileArchive
supplied to the Lambda resource. The problem is as follows. The default system Python is 3.10 and I can't simply change it because it breaks some things (e.g. APT package manager). I thus manually create the
venv
directory for Pulumi with
python3.11 -m venv venv
. I expect that when running
pulumi up
, the Pulumi program runs in context of the virtual env, i.e. using
pip
from the virtual env and also pointing the
python
binary to the one from virtual env. But it's not the case, it uses Python 3.10 system default instead. That's a problem, because one of the dependencies is Pydantic (via AWS Lambda Powertools) and it needs the installed version to exactly match the target runtime platform. It fails running the Lambda function, because the installed
pydantic-core
package is for Python 3.10 while the runtime is Python 3.11. It fails with
Copy code
Unable to import module 'lambda_function': No module named 'pydantic_core._pydantic_core'
If I temporarily switch the system default to Python 3.11 (using alternatives), it works and correctly installs the package for Python 3.11. I know I can manually switch to the virtual env prior to running
pulumi up
, it's just about the expectations. Thanks
d
do you mean
runtime.options.virtualenv
specified in
Pulumi.yaml
?
p
Yeah, sorry, missed the
options
in the path.
d
and
./venv/bin/python --version
gives you Python 3.11.x?
p
Yes
d
I'm a little unclear what issue you're describing. Is it that when you're using
pip
, it's installing the wrong versions, or that pulumi isn't using the venv?
p
That's the same thing, or more precisely, the former is caused by the later.
pip
is a Python script which contains a shebang with path to the Python interpreter. When Pulumi is not using the
venv
,
pip
uses the wrong Python interpreter (on a system path)
d
so if you do
source .venv/bin/activate
(ie, use the venv in current shell), it all works. But without, pulumi defaults to using the system python env for running and installing. Can you post the contents of
Pulumi.yaml
, can redact anything sensitive?
sorry for my confusion on the
pip
side, I wasn't aware pulumi did dependency management. Always managed my own venvs 🙂
p
so if you do
source .venv/bin/activate
(ie, use the venv in current shell), it all works.
Yes, exactly.
But without, pulumi defaults to using the system python env for running and installing.
That's not exactly what I stated (and hence the question). Pulumi clearly uses the
venv
for installing the dependencies and also interpreting the Pulumi program. It just doesn't switch to the virtualenv. (And thus, when using
local.Command
with command like
pip install ...
, it uses the
pip
on system path instead the one in the virtualenv.)
Well, the project file is quite simple:
Copy code
name: xxx-prod
description: xxx
runtime:
  name: python
  options:
    virtualenv: venv
options:
  refresh: always
d
ok, I see. sorry, I hadn't picked up on that. This is likely a limitation as local.Command will be run from a different process. You'll need to activate the venv as part of the script you're running
p
Yeah, that's probably it, it didn't come to my mind that
local.Command
would most probably run the command in a subprocess... Thanks!
d
I think for the case of the Python runtime,
local.Command
should use the venv as well. It's worth raising a feature request. I've similar problems with passing Google Auth tokens around, and it'd be good to see functionality to remove this kind of boilerplate
g
Hi, I decided to not use
runtime.virtualenv
config at all because I've had multiple projects using the same VENV and just used
poetry shell
before I started working. Nevertheless, I also made a mistake of using pedantic for
pulumi.ComponentResource
which resulted in a lot of unnecessary type headaches with outputs. Apart from that I used ASDF to manage my python installations and sometimes Pulumi just did not register the PATH to python binary correctly 🤷 (perhaps it has to do something with multiple PyCharm windows I had opened) In the end, I decided to move to TypeScript because it is much easier to express and write for pulumi. Mainly due to required boilerplate of for python classes (this ma be a gamechanger though https://github.com/pulumi/pulumi/issues/11732) As for lambdas, I find your solution interesting. I settled on dissociating the artifact from pulumi and just give pulumi an S3 path of pre-built package, so that lambda can use any runtime and I can write a more generic/flexible component.