Obter, adicionar, escrever por cima e apagar variáveis de ambiente em Python (os.environ)

O negócio

As variáveis ambientais podem ser recuperadas, verificadas, definidas (adicionadas ou sobrescritas), e apagadas em programas Python utilizando os.environ. Note-se que as alterações feitas através da definição ou eliminação de variáveis de ambiente só são efectivas dentro do programa Python. Isto não significa que as variáveis de ambiente do sistema serão reescritas.

A seguinte informação é fornecida aqui.

  • os.environ
  • Obter variáveis de ambiente.
  • Definir variáveis de ambiente (add\overwrite)
  • Remover variáveis de ambiente
  • Efeito das variáveis de ambiente em mudança
  • Mudança de processos por variáveis de ambiente

Importar e utilizar o módulo os. Uma vez que é uma biblioteca padrão, não é necessária qualquer instalação adicional. O módulo de subprocesso está também incluído na biblioteca padrão.

import os
import subprocess

os.environ

O tipo de os.environ é os._Environ.

print(type(os.environ))
# <class 'os._Environ'>

os._Environ é um objecto do tipo mapa com um par de chave e valor, e tem os mesmos métodos que um dicionário (tipo dict). O nome da variável ambiente é chave, e o seu valor é valor.

O conteúdo do os.environ será carregado quando o módulo os for importado. O conteúdo do os.environ não será actualizado mesmo que as variáveis de ambiente do sistema sejam alteradas por outros meios enquanto o programa estiver em execução.

A lista é apresentada com impressão().

# print(os.environ)

Tal como no dicionário, pode utilizar os seguintes métodos, ou utilizá-los para verificar a existência de chaves e valores.

  • keys()
  • values()

O processamento de chaves e valores é basicamente o mesmo que para os dicionários. Apresentam-se a seguir alguns exemplos.

Obter variáveis de ambiente.

os.environ[Environment variable name]
Isto permitir-lhe-á obter o valor da variável de ambiente, mas se especificar um nome de variável de ambiente que não existe, receberá um erro (KeyError).

print(os.environ['LANG'])
# ja_JP.UTF-8

# print(os.environ['NEW_KEY'])
# KeyError: 'NEW_KEY'

O método get() de os.environ pode ser utilizado para obter o valor por defeito se não existir. Isto é também o mesmo que o dicionário.

print(os.environ.get('LANG'))
# ja_JP.UTF-8

print(os.environ.get('NEW_KEY'))
# None

print(os.environ.get('NEW_KEY', 'default'))
# default

A função os.getenv() também é fornecida. Tal como o método get() do dicionário, devolve o valor por defeito se a chave não existir. Esta função é útil se apenas se quiser obter e verificar o valor de uma variável de ambiente.

print(os.getenv('LANG'))
# ja_JP.UTF-8

print(os.getenv('NEW_KEY'))
# None

print(os.getenv('NEW_KEY', 'default'))
# default

Definir variáveis de ambiente (add\overwrite)

os.environ[Environment variable name]
Ao atribuir um valor a isto, é possível definir uma variável de ambiente.

Quando um novo nome de variável de ambiente é especificado, a variável de ambiente é recentemente adicionada, e quando um nome de variável de ambiente existente é especificado, o valor da variável de ambiente é sobrescrito.

os.environ['NEW_KEY'] = 'test'

print(os.environ['NEW_KEY'])
# test

os.environ['NEW_KEY'] = 'test2'

print(os.environ['NEW_KEY'])
# test2

Note-se que a atribuição de algo que não seja uma corda resultará num erro (TypeError). Se quiser atribuir um valor numérico, especifique-o como uma cadeia de caracteres.

# os.environ['NEW_KEY'] = 100
# TypeError: str expected, not int

os.environ['NEW_KEY'] = '100'

A função os.putenv() também é fornecida. No entanto, o valor de os.environ não é actualizado quando é definido por os.putenv(). Por esta razão, é preferível especificar a chave (nome da variável de ambiente) de os.environ e atribuir o valor como mostrado no exemplo acima.

Se putenv() for suportado, uma atribuição a um item em os.environ será automaticamente convertida para uma chamada correspondente a putenv(). Na prática, a atribuição a um item em os.environ é a operação preferida, uma vez que uma chamada directa a putenv() não irá actualizar os.environ.
os.putenv() — Miscellaneous operating system interfaces — Python 3.10.0 Documentation

Como mencionado anteriormente, as alterações feitas pela adição ou sobreposição de variáveis de ambiente só são efectivas dentro do programa Python. Isto não significa que as variáveis de ambiente do sistema serão reescritas.

Note-se que a alteração do valor pode causar uma fuga de memória, dependendo do SO.

Nota: Em algumas plataformas, incluindo FreeBSD e Mac OS X, a alteração do valor do ambiente pode causar uma fuga de memória.
os.putenv() — Miscellaneous operating system interfaces — Python 3.10.0 Documentation

Isto deve-se à especificação putenv() do próprio sistema operativo.

Successive calls to setenv() or putenv() assigning a differently sized value to the same name will result in a memory leak. The FreeBSD seman-tics semantics for these functions (namely, that the contents of value are copied and that old values remain accessible indefinitely) make this bug unavoidable.
Mac OS X Manual Page For putenv(3)

Remover variáveis de ambiente

Para eliminar uma variável de ambiente, utilizar o método pop() de os.environ ou a declaração del. O mesmo que o dicionário.

O seguinte é um exemplo de pop().

pop() devolve o valor da variável de ambiente que foi eliminada. Por defeito, especificar uma variável de ambiente que não existe resultará num erro (KeyError), mas especificar o segundo argumento devolverá o valor da variável de ambiente se esta não existir.

print(os.environ.pop('NEW_KEY'))
# 100

# print(os.environ.pop('NEW_KEY'))
# KeyError: 'NEW_KEY'

print(os.environ.pop('NEW_KEY', None))
# None

O seguinte é um exemplo de del.

A variável ambiente é novamente adicionada, e depois apagada. Se a variável de ambiente não existir, um erro (KeyError).

os.environ['NEW_KEY'] = '100'

print(os.getenv('NEW_KEY'))
# 100

del os.environ['NEW_KEY']

print(os.getenv('NEW_KEY'))
# None

# del os.environ['NEW_KEY']
# KeyError: 'NEW_KEY'

A função os.unsetenv() também é fornecida. Contudo, tal como com os.putenv(), o valor de os.environ não é actualizado quando é apagado por os.unsetenv(). Portanto, é preferível especificar a chave (nome da variável de ambiente) de os.environ e eliminá-la como se mostra no exemplo acima.

Se o unsetenv() for suportado, a eliminação de um item em os.environ traduz automaticamente para a chamada correspondente ao unsetenv(). Na prática, apagar itens em os.environ é a operação preferida, uma vez que chamadas directas para unsetenv() não irão actualizar os.environ.
os.unsetenv() — Miscellaneous operating system interfaces — Python 3.10.0 Documentation

A eliminação de variáveis de ambiente também só é eficaz dentro desse programa Python. Não remove as variáveis de ambiente do sistema.

Efeito das variáveis de ambiente em mudança

Como tenho escrito repetidamente, alterar (definir ou apagar) a variável de ambiente os.environ não altera a variável de ambiente do sistema, mas afecta os subprocessos que são lançados no programa.

O seguinte código não funcionará como esperado no Windows porque não há variável de ambiente LANG e o conteúdo do comando de data é diferente.

Chamar o comando de data no módulo de subprocesso.

O resultado de saída do comando de data muda em função do valor da variável de ambiente LANG.

print(os.getenv('LANG'))
# ja_JP.UTF-8

print(subprocess.check_output('date', encoding='utf-8'))
# 2018年 7月12日 木曜日 20時54分13秒 JST
# 

os.environ['LANG'] = 'en_US'

print(subprocess.check_output('date', encoding='utf-8'))
# Thu Jul 12 20:54:13 JST 2018
# 

Por uma questão de explicação, alterámos a variável de ambiente LANG em os.environ, mas Python fornece um módulo locale para controlar o locale.

Mudança de processos por variáveis de ambiente

Também é possível mudar o processo de acordo com o valor de uma variável de ambiente.

Aqui está um exemplo de alteração da saída de acordo com a variável de ambiente LANG nas definições de idioma. Aqui estamos a usar o método startswith() para determinar se a string começa com a string especificada, mas se quiser determinar a correspondência exacta, pode usar “==” para comparar.

print(os.getenv('LANG'))
# en_US

if os.getenv('LANG').startswith('ja'):
    print('こんにちは')
else:
    print('Hello')
# Hello

os.environ['LANG'] = 'ja_JP'

if os.getenv('LANG').startswith('ja'):
    print('こんにちは')
else:
    print('Hello')
# こんにちは

Além disso, se as variáveis ambientais forem definidas para indicar o ambiente de desenvolvimento e o ambiente de produção, por exemplo, é possível obter os valores destas variáveis e mudar o processo.