# Replit + pip 

We’re thrilled to announce that first-class pip support is now available on Replit! This should work out-of-the-box when importing existing repositories from GitHub. For developers who want to switch from poetry to pip: start by deleting poetry.lock, then move your dependencies over from [tool.poetry.dependencies] to requirements.txt (structure hint: flask = "^3.0.2" would become flask>=3.0.2,<4 in requirements.txt), and finally, delete the other [tool.poetry...] sections from pyproject.toml. After that, the packaging infrastructure will use pip for all future operations going forward.

**Featured image unavailable: Cover artwork for the article “Replit + pip”.**

[Open original](https://replit.com/api/storage/public-objects/article-media/pip/sanity-1f713d1505f4311ef0c4e76ac4678a3a270b1db0.51c16de6ba0c98a0.webp)

- Published: 2024-02-15T17:00:00.000Z
- Authors: Devon Stewart
- Canonical: https://replit-engineering-blog.pages.dev/pip/

---

## First-class pip support

We’re thrilled to announce that first-class [pip](https://pypi.org/project/pip/) support is now available on Replit\! This should work out-of-the-box when importing existing repositories from GitHub. For developers who want to switch from poetry to pip: start by deleting `poetry.lock`, then move your dependencies over from `[tool.poetry.dependencies]` to `requirements.txt` (structure hint: `flask = "^3.0.2"` would become `flask>=3.0.2,<4` in `requirements.txt`), and finally, delete the other `[tool.poetry...]` sections from `pyproject.toml`. After that, the packaging infrastructure will use pip for all future operations going forward.

**Image unavailable: Shell output from installing a Python package with pip.**

[Open original](https://replit.com/api/storage/public-objects/article-media/pip/sanity-dc4bec9b63c3c4707743c6ea1289a1232698ddcd.516e4e7a819accbd.webp)

## Where we started

When we first chose how to support Python packaging, we went with [poetry](https://python-poetry.org/): a newer packager, offering a compelling feature set. While we stand by the value of having reproducibility and the stability that brings, we also acknowledge the significance of pip as a tool in the wider Python ecosystem.

One challenge we were trying to address in this change came in the form of following suggestions from AI assistants, StackOverflow, or blog posts that were written with the framing of `pip` being the “standard” packaging interface. Packages installed in this way would exist in an ephemeral state: both immediately available for use, but not yet recorded in the dependency list. This would no doubt result in frustration as a project that ran fine interactively in a Repl resulted in a `ModuleNotFoundError` during deployment.

## How we solved it

Fortunately, since [upm (Universal Package Manager)](https://github.com/replit/upm/) underpins the Replit Workspace package manager, the majority of the work to support pip could be done in one place. The biggest challenge was providing a nice user experience when `upm add`-ing a package. This came in the form of creating a pip UPM backend, as well as modifying the argument parser to be able to unpack version specifications when supplied directly on the CLI, mirroring `poetry add` and `pip install`’s CLI semantics.

To accomplish this, we wrote a `requirements.txt` parser, following the following standards: [PEP-423](https://peps.python.org/pep-0423/), [PEP-440](https://peps.python.org/pep-0440/), [PEP-508](https://peps.python.org/pep-0508/), as well as checking our implementation against the [PyPA specifications](https://packaging.python.org/en/latest/specifications/). Additionally, we reimagined the pip user experience to be in a better place for [when a pip lockfile is supported natively](https://discuss.python.org/t/what-is-the-status-on-a-pip-lock-file/6669). Instead of just taking a snapshot of all installed packages (as `pip freeze` does), we filter that list down to only the packages that we have just installed. This prevents the list of all transitive dependencies from ending up in `requirements.txt` with tightly constrained version ranges, making further upgrades difficult.

## Plan for the future

While we are happy to share the work we’ve been doing, this is only the beginning. We aim to make it easier to [onboard new package managers](https://github.com/replit/upm/labels/enhancement) to UPM, as well as continuing to build out the supporting Golang functions for interoperating with the Python ecosystem. Some areas for research include: better support for [PEP-517](https://peps.python.org/pep-0517/) and [PEP 518](https://peps.python.org/pep-0518/), offering “migration” tooling from `requirements.txt` to `pyproject.toml`, or deeper analysis into package structure to improve `upm guess`.

If this work sounds interesting to you, check out our [Careers page](https://replit.com/site/careers)\!
