Qual é uma boa prática para verificar se uma variável ambiental existe ou não?

130

Quero verificar meu ambiente quanto à existência de uma variável, digamos "FOO", em Python. Para esse fim, estou usando a osbiblioteca padrão. Depois de ler a documentação da biblioteca, descobri duas maneiras de atingir meu objetivo:

Método 1:

if "FOO" in os.environ:
    pass

Método 2:

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

Gostaria de saber qual método, se houver, é um condicional bom / preferido e por quê.

Kshitij Saraogi
fonte
É principalmente baseado em opiniões. Ambos servem ao mesmo propósito. I vai preferir o método 1, uma vez que é mais limpo
Moinuddin Quadri
1
Não posso dizer que há algo nele. Escolha uma (jogue uma moeda?) E reavalie depois se ela não funcionar. Sinceramente, acho que você passou mais tempo digitando esta pergunta do que economizaria de qualquer maneira!
jonrsharpe
1
@Ayoub: Acho que você esqueceu de ver a pergunta "Qual é uma boa prática para verificar se uma variável ambiental existe ou não no Python?"
Moinuddin Quadri
1
Opinião baseada. A sintaxe do método 1 serve melhor, já que você pergunta se fooestá nos envários, não se procura fooresultados em Nonevalores.
Uriel
1
Mas dessa forma pode não ser óbvio, a menos que você seja holandês ...
jonrsharpe

Respostas:

168

Use o primeiro; ele tenta diretamente verificar se algo está definido environ. Embora a segunda forma funcione igualmente bem, ela está faltando semanticamente, pois você recebe um valor de volta, se existir, e o usa apenas para comparação.

Você está tentando ver se algo está presente em environ , por que você iria ficar apenas para compará-lo e depois lançá-lo afastado ?

É exatamente getenvisso que faz:

Obtenha uma variável de ambiente e retorne Nonese ela não existir. O segundo argumento opcional pode especificar um padrão alternativo.

(isso também significa que seu cheque pode ser apenas if getenv("FOO"))

você não deseja obtê-lo , deseja verificar sua existência.

De qualquer forma, getenvé apenas um invólucroenviron.get mas você não vê pessoas verificando a associação em mapeamentos com:

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

Para resumir, use:

if "FOO" in os.environ:
    pass

se você apenas deseja verificar a existência, enquanto, use getenv("FOO")se você realmente deseja fazer algo com o valor que você pode obter.

Dimitris Fasarakis Hilliard
fonte
2
Obrigado pela sua explicação. Manterei isso em mente.
Kshitij Saraogi
29

Há um caso para qualquer solução, dependendo do que você deseja fazer, dependendo da existência da variável de ambiente.

Caso 1

Quando você deseja executar ações diferentes com base na existência da variável de ambiente, sem se importar com seu valor, a primeira solução é a melhor prática. Descreve sucintamente o que você testa: é 'FOO' na lista de variáveis ​​de ambiente.

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

Caso 2

Quando você deseja definir um valor padrão, se o valor não for definido nas variáveis ​​de ambiente, a segunda solução é realmente útil, embora não no formato que você escreveu:

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

ou talvez

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

Observe que, se você tiver várias opções para o seu aplicativo, poderá procurar ChainMap, o que permite mesclar vários dictos com base em chaves. Há um exemplo disso na ChainMapdocumentação:

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

Para estar no lado seguro, use

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

Um caso de canto com as respostas acima é quando a variável de ambiente está definida, mas está vazia

Para este caso especial, você obtém

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

Para evitar isso, use or

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

Então você recebe

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

Quando temos variáveis ​​de ambiente vazias?

Você esqueceu de definir o valor no .envarquivo

# .env
FOO=

ou exportado como

$ export FOO=

ou esqueceu de configurá-lo settings.py

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

Atualização: em caso de dúvida, confira essas orientações

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

$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"
Levon
fonte
A assinatura para getenv é def getenv(key, default=None):assim que se forma que deve permitir um padrão vs o ou sintaxe no início
Chris McKee
@Chris McKee tente isto #>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar'))
Levon
Assinatura enganosa do método
Chris
1
@ Chris McKee, outro exemplo$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"
Levon
3

Caso deseje verificar se várias variáveis ​​env não estão definidas, você pode fazer o seguinte:

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))
vhamon
fonte
-1

Meu comentário pode não ser relevante para as tags fornecidas. No entanto, fui levado a esta página da minha pesquisa. Eu estava procurando uma verificação semelhante no R e vim a seguir com a ajuda do post @hugovdbeg. Espero que seja útil para alguém que está procurando uma solução semelhante em R

'USERNAME' %in% names(Sys.getenv())
sveer
fonte