web-dev-qa-db-fra.com

L'exécution d'un script python à partir de virtualenv bin ne fonctionne pas

J'ai un script que je veux être disponible globalement. J'ai commencé avec le hashbang standard:

#! /usr/bin/env python

Et l'a lié au répertoire bin de mon virtualenv:

~/environments/project/env/bin/myscript

Et ajouté ce répertoire à mon chemin. Quand je lance la commande:

myscript

Je reçois une erreur d'importation avec l'une des bibliothèques. Cependant, si j'active l'environnement virtuel et exécute le script, cela fonctionne comme prévu.

J'ai écarté un problème avec le lien symbolique (j'ai aussi essayé de déplacer le script dans le dossier bin). J'ai aussi essayé d'exécuter le script avec Python

python ~/environments/project/env/bin/myscript

Auparavant, j'utilisais un script qui activait l'environnement puis exécutait mon script, mais j'avais l'impression que le script exécuté à partir de ce dossier devait s'exécuter avec les interpréteurs et les packages de site de virtualenv. Des idées de pourquoi ceci pourrait ne pas fonctionner ou des manières que je pourrais le déboguer?

24
justin

Le fait de placer le script dans le bac de votre virtualenv, puis d'ajouter cet emplacement à votre PATH global ne générera pas automatiquement votre virtualenv. Vous devez d'abord le rechercher pour le rendre actif. 

Tout ce que votre système sait, c'est vérifier ce chemin supplémentaire pour l'exécutable et l'exécuter. Il n'y a rien dans ce script indiquant un virtualenv.

Vous pouvez cependant coder en dur la ligne she-bang sur votre python virtualenv, auquel cas les paquets de site se retrouveront sur le chemin:

#!/Users/foo/environments/project/env/bin/python

Ou une autre option consiste simplement à créer un petit wrapper bash qui appelle votre script pythons d'origine, ce qui vous permettra de laisser votre script original avec un she-bang générique.

Donc si myscript.py est: #!/usr/bin/env python ...

Ensuite, vous pouvez faire un myscript:

#!/bin/bash

/Users/foo/environments/project/env/bin/python myscript.py

Quand vous faites myscript, il appellera explicitement votre script python avec l'interpréteur que vous avez configuré.

41
jdi

Je pense que vous ne savez pas comment fonctionne virtualenv.

En un mot, virtualenv modifie votre environnement Shell afin que Python recherche dans différents domaines les modules que vous souhaitez importer. Il n'y a pas vraiment de relation entre l'emplacement de stockage de votre environnement virtuel et l'emplacement de stockage des fichiers source que vous exécutez dans virtualenv. Si vous le souhaitez, vous pouvez stocker votre virtualenv dans un répertoire appelé ~ /vironnements/my_env, ainsi que toutes les sources que vous codez lorsque vous utilisez virtualenv dans ~/projects/my_proj.

Vous pouvez en savoir plus sur ce que virtulenv fait dans la documentation.

En réalité, la seule chose qui indique à python où trouver les modules est entièrement basée sur python ( voir la documentation sur le fonctionnement de celui-ci). L'activation de virtualenv modifie le fonctionnement de python.

Vous pouvez revenir à un script Shell pour activer virtualenv pour vous ou vous pouvez suivre cette recette pour l'activer directement à partir de votre script.

activate_this = '/path/to/env/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))

Si vous choisissez cette route, gardez les informations mentionnées par la documentation:

Cela va changer sys.path et même changer sys.prefix, mais aussi permettre vous utilisez un interprète existant. Les éléments de votre environnement seront apparait en premier sur sys.path, avant les éléments globaux. Cependant, les éléments globaux sera toujours accessible (comme si l'indicateur --system-site-packages avait été utilisé pour créer l'environnement, que ce soit ou non). Également, cela ne peut pas annuler l'activation d'autres environnements, ou de modules qui ont été importés. Vous ne devriez pas essayer, par exemple, d’activer un fichier environnement avant une demande Web; vous devez activer un environnement dès que possible, et ne pas le refaire dans ce processus.

10
Mark Hildreth

Ne pourriez-vous pas simplement ajouter un chemin relatif à la place? Cela a fonctionné pour moi:

#!./env/bin/python
2
Carvaka

J'ai rencontré le même problème et ai proposé cette solution: https://github.com/jabbalaci/wpython . C'est un script appelé "wpython" qui appelle votre programme avec l'interpréteur Python local dans votre fichier. Ainsi, au lieu de "/Users/foo/environments/project/env/bin/python myscript.py", il suffit d'écrire "wpython /path/to/myscript.py". Un script de lanceur pourrait ressembler à ceci:

#!/usr/bin/env bash

cd /the/directory/where/myscript.py/is/located
wpython myscript.py
0
Jabba

Si vous utilisez Windows, vous pouvez inclure la ligne suivante en haut du fichier python. 

#! P:\Workspace\pythontut\Scripts python
0
user1012513