Quelle est une bonne pratique pour vérifier si une variable environnementale existe ou non?


130

Je veux vérifier dans mon environnement l'existence d'une variable, par exemple "FOO", en Python. Pour cela, j'utilise la osbibliothèque standard. Après avoir lu la documentation de la bibliothèque, j'ai trouvé 2 façons d'atteindre mon objectif:

Méthode 1:

if "FOO" in os.environ:
    pass

Méthode 2:

if os.getenv("FOO") is not None:
    pass

Je voudrais savoir quelle méthode, le cas échéant, est une bonne / préférée conditionnelle et pourquoi.


Il est principalement basé sur l'opinion. Les deux ont le même objectif. Je préférerai la méthode 1 car elle est plus propre
Moinuddin Quadri

1
Je ne peux pas dire qu'il y ait quelque chose dedans. Choisissez-en une (lancez une pièce?) Et réévaluez plus tard si cela ne fonctionne pas. Franchement, je pense que vous avez passé plus de temps à taper cette question que vous n'en économiseriez de toute façon!
jonrsharpe

1
@Ayoub: Je pense que vous avez oublié de voir la question "Quelle est une bonne pratique pour vérifier si une variable d'environnement existe ou non en Python?"
Moinuddin Quadri

1
Basé sur l'opinion. La syntaxe de la méthode 1 sert mieux, car vous demandez si fooest dans les variables d'environnement, pas si la recherche de foorésultats dans des Nonevaleurs.
Uriel

1
Mais cette voie n'est peut-être pas évidente, à moins que vous ne soyez néerlandais ...
jonrsharpe

Réponses:


168

Utilisez le premier; il essaie directement de vérifier si quelque chose est défini dans environ. Bien que la deuxième forme fonctionne aussi bien, elle manque sémantiquement puisque vous récupérez une valeur si elle existe et ne l' utilisez que pour une comparaison.

Vous essayez de voir si quelque chose est présent dans environ , pourquoi voudriez - vous faire juste pour le comparer puis le jeter loin ?

C'est exactement ce que getenvfait:

Obtenez une variable d'environnement , renvoyez-la Nonesi elle n'existe pas. Le deuxième argument facultatif peut spécifier une autre valeur par défaut.

(cela signifie également que votre chèque pourrait simplement être if getenv("FOO"))

vous ne voulez pas l' obtenir , vous voulez vérifier son existence.

Quoi qu'il en soit, ce getenvn'est qu'un wrapper, environ.getmais vous ne voyez pas de personnes vérifier leur adhésion dans les mappages avec:

from os import environ
if environ.get('Foo') is not None:

Pour résumer, utilisez:

if "FOO" in os.environ:
    pass

si vous voulez juste vérifier l'existence, tandis que, utilisez getenv("FOO")si vous voulez réellement faire quelque chose avec la valeur que vous pourriez obtenir.


2
Merci pour votre explication. Je garderai cela à l'esprit.
Kshitij Saraogi

29

Il existe un cas pour l'une ou l'autre solution, en fonction de ce que vous voulez faire sous réserve de l'existence de la variable d'environnement.

Cas 1

Lorsque vous souhaitez effectuer différentes actions uniquement basées sur l'existence de la variable d'environnement, sans vous soucier de sa valeur, la première solution est la meilleure pratique. Il décrit succinctement ce que vous testez: est «FOO» dans la liste des variables d'environnement.

if 'KITTEN_ALLERGY' in os.environ:
    buy_puppy()
else:
    buy_kitten()

Cas 2

Lorsque vous souhaitez définir une valeur par défaut si la valeur n'est pas définie dans les variables d'environnement, la deuxième solution est en fait utile, mais pas sous la forme que vous l'avez écrite:

server = os.getenv('MY_CAT_STREAMS', 'youtube.com')

ou peut-être

server = os.environ.get('MY_CAT_STREAMS', 'youtube.com')

Notez que si vous avez plusieurs options pour votre application, vous voudrez peut-être examiner ChainMap, ce qui permet de fusionner plusieurs dictionnaires en fonction des clés. Il y a un exemple de ceci dans la ChainMapdocumentation:

[...]
combined = ChainMap(command_line_args, os.environ, defaults)

15

Pour être du bon côté, utilisez

os.getenv('FOO') or 'bar'

Un cas de coin avec les réponses ci-dessus est lorsque la variable d'environnement est définie mais est vide

Pour ce cas spécial, vous obtenez

print(os.getenv('FOO', 'bar'))
# prints new line - though you expected `bar`

ou

if "FOO" in os.environ:
    print("FOO is here")
# prints FOO is here - however its not

Pour éviter cela, utilisez simplement or

os.getenv('FOO') or 'bar'

Ensuite, vous obtenez

print(os.getenv('FOO') or 'bar')
# bar

Quand avons-nous des variables d'environnement vides?

Vous avez oublié de définir la valeur dans le .envfichier

# .env
FOO=

ou exporté en tant que

$ export FOO=

ou j'ai oublié de l'installer settings.py

# settings.py
os.environ['FOO'] = ''

Mise à jour: en cas de doute, découvrez ces one-liners

>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar'))

$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"

La signature pour getenv est def getenv(key, default=None):si oui, cela devrait permettre une syntaxe par défaut par rapport à la syntaxe ou au début
Chris McKee

@Chris McKee essayez ceci>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar'))
Levon

Signature de méthode trompeuse 😜
Chris McKee

1
@Chris McKee, un autre exemple$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"
Levon

3

Si vous souhaitez vérifier si plusieurs variables d'environnement ne sont pas définies, vous pouvez effectuer les opérations suivantes:

import os

MANDATORY_ENV_VARS = ["FOO", "BAR"]

for var in MANDATORY_ENV_VARS:
    if var not in os.environ:
        raise EnvironmentError("Failed because {} is not set.".format(var))

-1

Mon commentaire n'est peut-être pas pertinent pour les balises fournies. Cependant, j'ai été dirigé vers cette page à partir de ma recherche. Je cherchais un enregistrement similaire dans R et j'ai trouvé ce qui suit avec l'aide de @hugovdbeg post. J'espère que cela serait utile pour quelqu'un qui recherche une solution similaire dans R

'USERNAME' %in% names(Sys.getenv())
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.