¿Cómo puedo usar un archivo de requisitos pip para desinstalar e instalar paquetes?

90

Tengo un archivo de requisitos de pip que cambia durante el desarrollo.

¿Se pippuede hacer desinstalar paquetes que no aparecen en el archivo de requisitos así como instalar aquellos que sí aparecen? ¿Existe un método estándar?

Esto permitiría que el archivo de requisitos de pip sea la lista canónica de paquetes, un enfoque 'si y solo si'.

Actualización : lo sugerí como una nueva característica en https://github.com/pypa/pip/issues/716

wodow
fuente
3
¿REALMENTE desea que pip desinstale paquetes arbitrarios solo porque su programa no los requiere? Suena un poco peligroso ...
Scott Hunter
11
@ScottHunter Si estás en un virtualenv sin paquetes de sitio, es algo razonable que quieras hacer.
Michael Mior
1
@ScottHunter Sí, si utilizo un entorno controlado (virtual) en el que quiero estar seguro de lo que hay allí, y no hay nada más presente que pueda causar problemas, por ejemplo, dependencias inesperadas.
wodow
@MichaelMior Si esa es la respuesta, por favor agregue como respuesta y la aceptaré.
wodow
@wodow Hecho. La única razón por la que no publiqué como respuesta es porque probablemente hay una solución más útil que puede llevarlo a lo que desea.
Michael Mior

Respuestas:

16

La respuesta corta es no, no puedes hacer eso con pip.

Michael Mior
fuente
32
como dice Stephen a continuación:pip uninstall -r requirements.txt
Ommit
31
@Ommit Esto no desinstala los paquetes que no aparecen en el archivo de requisitos. Desinstala todos los paquetes que aparecen en el archivo.
Michael Mior
3
@ Micheal Mior, ah, no presté suficiente atención a la pregunta original. Culpa mía.
Ommit
4
Agregue un -yal comando de @Ommit para evitar tener que presionar Y e ingresar muchas veces. Aprende de mis errores.
Greg Hilston
1
Solo para agregar: pip uninstall -r requirements.txtsolo desinstalará las versiones en su requirements.txt. Si desinstala, boto3==1.10.0por ejemplo, pip freezese mostrará boto3==1.0.1si lo ha instalado (o alguna versión anterior) anteriormente.
Jordan Mackie
125

Esto debería desinstalar todo lo que no esté en requirements.txt:

pip freeze | grep -v -f requirements.txt - | grep -v '^#' | xargs pip uninstall -y

Aunque esto no funcionará del todo bien con paquetes instalados con -e, es decir, desde un repositorio git o similar. Para omitirlos, simplemente filtre los paquetes que comiencen con la -ebandera:

pip freeze | grep -v -f requirements.txt - | grep -v '^#' | grep -v '^-e ' | xargs pip uninstall -y

Entonces, obviamente:

pip install -r requirements.txt

Actualización para 2016: sin embargo, probablemente no quieras utilizar el enfoque anterior. Echa un vistazo pip-toolsypip-sync que logran lo que probablemente estás buscando hacer de una manera mucho más sólida.

https://github.com/nvie/pip-tools

Actualización para mayo de 2016:

Ahora también puede usar pip uninstall -r requirements.txt, sin embargo, esto logra básicamente lo contrario: desinstala todo enrequirements.txt

Actualización para mayo de 2019:

Echa un vistazo a pipenv . Han pasado muchas cosas en el mundo de la gestión de paquetes que hacen que este tipo de preguntas sea un poco obsoleto. Sin embargo, todavía estoy bastante feliz usando pip-tools.

Stephen Fuhry
fuente
5
Eso estaría bien. Me parece una buena manera de obligar a los desarrolladores a ser explícitos sobre sus dependencias rompiendo todo si instalan algo en un host manualmente sin actualizar su requirements.txt. Me interesaría ver qué tipo de comentarios generaría una solicitud de extracción que agregue esa funcionalidad.
Stephen Fuhry
¡Esta es la respuesta correcta! Pongo esto en mi project.configarchivo para Django en Elastic Beanstalk: 05_pip_clean: command: "pip freeze | grep -v -f requirements.txt - | grep -v '^#' | xargs pip uninstall -y". Ahora puedo deshacer los paquetes de pip sin reconstruir mi entorno con solo usar comentarios en requirements.txt. Esto me está ahorrando un tiempo de inactividad real. ¡Gracias!
e.thompsy
¿Alguna vez hay una salida de pip freeze que comienza con #? En otras palabras, ¿es necesario el segundo grep?
xor
1
No estoy seguro si pip freezehace comentarios, pero algún día pueden agregarlo a la API y, si lo hacen, será válido. Si no lo hacen, entonces lo anterior no es una operación. El guión le permite usar stdin del comando anterior, en este caso, el guión le dice a grep que compare el contenido de requirements.txt con la salida de pip freeze(la salida de pip freezeen este contexto es sinónimo de stdin)
Stephen Fuhry
1
Recomiendo encarecidamente pip-tools. +1
ron rothman
16

No es una característica de pip, no. Si realmente desea algo así, puede escribir un script para comparar el resultado pip freezecon el suyo requirements.txt, pero probablemente sería más complicado de lo que vale la pena.

Al usar virtualenv, es más fácil y confiable simplemente crear un entorno limpio y (re) instalar desde requirements.txt, como:

deactivate
rm -rf venv/
virtualenv venv/
source venv/bin/activate
pip install -r requirements.txt
dbr
fuente
6
Podría ser útil simplemente desinstalar paquetes que no están en el archivo de requisitos si algunos de los paquetes (PIL, lxml, etc.) requieren una compilación prolongada, especialmente si esto se lleva a cabo en un servidor en vivo que usa el entorno virtual.
melinath
@melinath Si no están en su archivo de requisitos y ya están instalados, entonces la compilación no debería tener que volver a ocurrir.
Michael Mior
1
@MichaelMior: a menos que, digamos, borre todo el virtualenv, como sugiere esta respuesta.
melinath
1
@melinath Pero si borra el virtualenv y el paquete no es necesario (y no está en su requirements.txt), ¿por qué volvería a instalarse?
Michael Mior
3
@MichaelMior Intentaré expresar mi comentario original de manera más explícita. Parece que puede haber entendido mal el punto que estaba diciendo. Imagine un archivo de requisitos simple que contiene PIL y lxml. Pero luego decide que ya no necesita lxml y lo elimina del archivo de requisitos. Si hace lo que sugiere esta respuesta y borra el virtualenv, debe reinstalar (y recompilar) PIL. Sería más eficiente tener la opción de simplemente desinstalar lxml (es decir, todos los paquetes que no están en el archivo de requisitos)
melinath
11

Ahora puede pasar el -r requirements.txtargumento a pip uninstall.

pip uninstall -r requirements.txt -y

Al menos a partir de pip8.1.2, pip help uninstallmuestra:

...
Uninstall Options:
  -r, --requirement <file>    Uninstall all the packages listed in the given requirements file.  This option can be
                              used multiple times.
...
Joseph sintoísta
fuente
3
Esto no desinstala paquetes que no aparecen en el archivo. Se desinstala paquetes que no aparecen en el archivo.
Michael Mior
4

Esta es una pregunta antigua (pero buena) y las cosas han cambiado sustancialmente desde que se planteó.

Hay una referencia informal a pip-syncen otra respuesta, pero merece su propia respuesta, porque resuelve precisamente el problema del OP.

pip-sync toma un requirements.txtarchivo como entrada y "ajusta" su entorno Python actual para que coincida exactamente con lo que contienerequirements.txt . Esto incluye eliminar cualquier paquete que esté presente en su entorno pero ausente requirements.txt.

Ejemplo: Supongamos que queremos que nuestro env para contener (sólo) 3: bibliotecas libA, libBy libC, así:

> cat requirements.txt
libA==1.0
libB==1.1
libC==1.2

Pero nuestro env contiene actualmente libCy libD:

> pip freeze
libC==1.2
libD==1.3

Ejecutar pip-sync resultará en esto, que era nuestro estado final deseado:

> pip-sync requirements.txt
> pip freeze
libA==1.0
libB==1.1
libC==1.2
ron rothman
fuente
tenga cuidado, si tiene un pip-tools instalado globalmente, no se desinstalará en su virtualenv actualmente activado ... sigue siendo extraño, pero por lo demás es la herramienta de gestión de requisitos más sencilla que conozco.
benzkji
3

La propuesta de Stephen es una buena idea, pero desafortunadamente no funciona si solo incluye requisitos directos en su archivo, lo que me suena más limpio.

Se desinstalarán todas las dependencias, incluso distribute, se descompondrá pip.

Mantener un archivo de requisitos limpio mientras la versión rastrea un entorno virtual

Así es como trato de rastrear la versión de mi entorno virtual. Intento mantener un mínimo requirements.txt, incluidos solo los requisitos directos, y ni siquiera mencionar las restricciones de versión donde no estoy seguro.

Pero además, guardo e incluyo en el seguimiento de versiones (digamos git), el estado real de mi virtualenv en un venv.piparchivo.

Aquí hay un flujo de trabajo de muestra:


configurar el espacio de trabajo virtualenv, con seguimiento de versiones:

mkdir /tmp/pip_uninstalling
cd /tmp/pip_uninstalling
virtualenv venv
. venv/bin/activate

inicializar el sistema de seguimiento de versiones:

git init
echo venv > .gitignore
pip freeze > venv.pip
git add .gitignore venv.pip
git commit -m "Python project with venv"

instale un paquete con dependencias, inclúyalo en el archivo de requisitos:

echo flask > requirements.txt
pip install -r requirements.txt
pip freeze > venv.pip

Ahora comience a construir su aplicación, luego confirme y comience una nueva rama:

vim myapp.py
git commit -am "Simple flask application"
git checkout -b "experiments"

instalar un paquete adicional:

echo flask-script >> requirements.txt
pip install -r requirements.txt
pip freeze > venv.pip

... juega con él y luego vuelve a la versión anterior

vim manage.py
git commit -am "Playing with flask-script"
git checkout master

Ahora desinstale los paquetes extraños:

pip freeze | grep -v -f venv.pip | xargs pip uninstall -y

Supongo que el proceso se puede automatizar con git hooks, pero no salgamos del tema.

Por supuesto, entonces tiene sentido usar algún sistema de almacenamiento en caché de paquetes o repositorio local como pip2pi

Camino rocoso
fuente
2

A cuestas @ stephen-j-fuhry aquí hay un equivalente de PowerShell que uso:

pip freeze | ? { $_ -notmatch ((gc req.txt) -join "|") }
egbutter
fuente
0

Si bien esto no responde directamente a la pregunta, una mejor alternativa a requirements.txtahora es usar un Pipfile. Esto funciona de manera similar a Ruby Gemfile. Actualmente, necesita hacer uso de la pipenvherramienta, pero es de esperar que esto finalmente se incorpore a pip. Esto proporciona el pipenv cleancomando que hace lo que quiere.

(Tenga en cuenta que puede importar un existente requirements.txtcon pipenv install -r requirements.txt. Después de esto, debería tener un Pipfiley requirements.txtse puede eliminar).

Michael Mior
fuente
-3

Ahora es posible usar:

pip uninstall -r requirements.txt
Roberto Nunes
fuente
2
Esto no desinstala los paquetes que no aparecen en el archivo de requisitos. Se desinstala todos los paquetes que no aparecen en el archivo.
Michael Mior