# Julia equivalent of the \`.venv\` folder when working with Pkg and environments

**URL:** <https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123>\
**Category:** New to Julia\
**Created:** [November 1, 2024, 11:29am UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123 "2024-11-01T11:29:20Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 1, 2024, 11:29am UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/1 "2024-11-01T11:29:20Z")

</div>

I have realized I am a little confused about one aspect of the behavior of `Pkg`.

In Python, local virtual environments are provided by `venv`. (Other tools also exist.)

You use Python to run `venv`, which is a globally accessible Python module. Creating a virtual environment in the current working directory will create a folder which contains any packages which are added when this local environment is active.

It works like this:

```julia
$ which pip3
/usr/bin/pip3 # can't remember exactly where it lives, but
# by default the package manager is the global instance
$ python3 -m venv .venv # the directory is named `.venv`
$ ./.venv/bin/activate
(.venv) $ # the environment is now active
(.venv) $ which pip3
./venv/bin/pip3 # the package manager is now the
# local package manager, rather than the global instance
(.venv) $ pip3 install pandas
...
# the folder `.venv` now contains the downloaded
# package `pandas`

```

With Julia and `Pkg`, the situation is somehow different. A `Project.toml` is created, but there is no local directory which stores data for downloaded packages.

As far as I am aware, there is also no way to “activate” the environment in your current shell, such that `pkg> add X` installs `X` in the local environment rather than defaulting to the global (system wide) one.

Just wondering if anyone can provide some helpful commentary on some of these points? In particular, how does this machinery work, without an equivalent of a (local) `.venv` folder?

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [November 1, 2024, 11:35am UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/2 "2024-11-01T11:35:23Z")

</div>

> [@world-peace](#):
>
> As far as I am aware, there is also no way to “activate” the environment in your current shell, such that `pkg> add X` installs `X` in the local environment rather than defaulting to the global (system wide) one.

Just do:

```julia
]
activate .

```

or

```julia
using Pkg
Pkg.activate(".")

```

And to answer your second question, the packages are installed in `.julia/packages`. Yes, this folder is shared by all environments, but which specific versions are loaded for a specific project is stored in the file `Manifest.toml`.

So if you start Julia in a project folder using either `julia --project` or start Julia in the global environment and than activate the local project, then Julia loads the exact package versions as remembered in the `Manifest.toml` file.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [November 1, 2024, 11:42am UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/3 "2024-11-01T11:42:44Z")

</div>

I’m not a Python so not sure what `venv` does user but are you asking why doesn’t Julia install the actual packages (i.e. their source code/compiled code/binaries) in a local folder? So that if you do:

```julia
pkg> activate @Env1

pkg> add DataFrames

pkg> activate @Env2

pkg> add DataFrames

```

you’d want to have two copies of `DataFrames` on your machine? Indeed that isn’t happening in Julia, rather `Pkg` will check whether the required version of a specific package is already installed and if so just use that.

Why would you want to duplicate that installation?

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 1, 2024, 11:55am UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/4 "2024-11-01T11:55:00Z")

</div>

> [@ufechner7](#):
>
> Just do:
> 
> ```julia
> ]
> activate .
> 
> ```

This does not persist if you close the REPL though.

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 1, 2024, 11:57am UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/5 "2024-11-01T11:57:39Z")

</div>

> [@nilshg](#):
>
> Why would you want to duplicate that installation?

Probably you wouldn’t. Maybe the way Python’s `venv` works is a less sensible approach.

One advantage this does have is you can “build” your environment and ship everything in a Docker container relatively easily by just copying the parent folder. This will also copy the `.venv` subfolder. It’s only useful if you are deploying to a machine with the same CPU architecture. (Some packages such as `numpy` are architecture dependent iirc.)

---

<div class="post-metadata">

**Author:** ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)\
**Post date:** [November 1, 2024, 12:12pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/6 "2024-11-01T12:12:08Z")

</div>

In some sense, you might consider the `Manifest.toml` file that is created when you instantiate the environment to be the “equivalent” to the local `.venv` folder.

As the previous responses point out, the actual data for the installed packages will be in `~/.julia`, in a way that reuses data if you have multiple environments that use the same version of the same dependency.

In Python, you get basically the same behavior if you manage environments with [Poetry](https://python-poetry.org) instead of the standard-library `venv` module. Many of the other “modern” Python packaging solutions have also switched to keeping the environment in a central location, but I’ve found Poetry in particular to be extremely close to how `Pkg` works in Julia.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [November 1, 2024, 12:27pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/7 "2024-11-01T12:27:22Z")

</div>

> [@world-peace](#):
>
> This does not persist if you close the REPL though.

This is true. It does persist if you use VSCode, though. If you are not using VSCode and if you are on Linux, just create an alias like

```julia
alias jl='julia --project'

```

and add this line to your `.bashrc` file.

---

<div class="post-metadata">

**Author:** ![jdad](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jdad/32/4739_2.png) [@jdad](https://discourse.julialang.org/u/jdad)\
**Post date:** [November 1, 2024, 12:43pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/8 "2024-11-01T12:43:01Z")

</div>

Or add `export JULIA_PROJECT=@.` in your `.bashrc`

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [November 1, 2024, 1:17pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/9 "2024-11-01T13:17:37Z")

</div>

Or put

```julia
import Pkg
isfile("Project.toml") && Pkg.activate(".")

```

in your `~/.julia/config/startup.jl`.

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 1, 2024, 2:31pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/10 "2024-11-01T14:31:28Z")

</div>

To give my personal opinion - I don’t really like to hide machinery which changes how Julia behaves when it starts up. It becomes easy to forget this isn’t the default if you have to go help someone else or work in a different environment. (eg a server somewhere which you do not control)

I do quite like the alias suggestion, because this introduces a separate command.

**Regardless, thanks for these suggestions, they are still interesting ideas to consider.**

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [November 2, 2024, 10:22am UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/11 "2024-11-02T10:22:25Z")

</div>

> [@world-peace](#):
>
> One advantage this does have is you can “build” your environment and ship everything in a Docker container relatively easily by just copying the parent folder. This will also copy the `.venv` subfolder.

I’m missing what you’re saying that is possible in Python but not in Julia. If you instantiate a Julia environment in a docker image, all its content is automatically present in the [depot](https://docs.julialang.org/en/v1/base/constants/#Base.DEPOT_PATH) (by default it’d be the `.julia` subdirectory of the home of the user, but if you want you can also set an [environment variable](https://docs.julialang.org/en/v1/manual/environment-variables/#JULIA_DEPOT_PATH) to use some other directory), without having to manually copy files around. Also, if I remember correctly, `venv` creates symlinks to the python executable, if you copy that directory from the host machine to inside the container you may end up with broken links.

> [@world-peace](#):
>
> It’s only useful if you are deploying to a machine with the same CPU architecture. (Some packages such as `numpy` are architecture dependent iirc.)

Julia optionally does [function multiversioning](https://docs.julialang.org/en/v1/devdocs/llvm-passes/#Multiversioning), which means that if you set the [`JULIA_CPU_TARGET`](https://docs.julialang.org/en/v1/manual/environment-variables/#JULIA_CPU_TARGET) environment variable appropriately the compiler generates code for a function optimised for all the chosen microarchitectures and that can be saved in the package precompile cache, and the program will decide at runtime which version of the native code to pick based on the CPU available.

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [November 2, 2024, 10:33am UTC](https://discourse.julialang.org/t/julia-equivalent-of-the-venv-folder-when-working-with-pkg-and-environments/122123/12 "2024-11-02T10:33:19Z")

</div>

> [@giordano](#):
>
> I’m missing what you’re saying that is possible in Python but not in Julia.

What I meant to say is you can write a line like `COPY . .` in your `Dockerfile` and assuming you are shipping to the same architecture, it will work.

It was kind of a dumb suggestion to be honest, and no one should really do this.

Better to do

```julia
RUN python3 -m venv .venv

RUN ./.venv/bin/pip3 install pandas
...

```

but I didn’t intend to turn this into a Docker thread.
