Python os e sys
Um programa não vive sozinho: ele roda dentro de um sistema operacional (o Ubuntu da Ana), numa pasta, com um usuário, e foi chamado por alguém, de algum jeito. Dois módulos da biblioteca padrão deixam o seu programa olhar em volta. O os (de operating system, "sistema operacional") conversa com o sistema: pastas, arquivos, variáveis de ambiente. O sys (de system, "sistema") conversa com o próprio Python: os argumentos que chegaram, a versão, onde ele procura os módulos e como encerrar o programa.
- Com o
os: a pasta atual (os.getcwd,os.chdir), o conteúdo de uma pasta (os.listdir), criar pastas (os.mkdir), testar se algo existe (os.path.exists). - As variáveis de ambiente com
os.environ, e por que.get()é mais seguro que[…]. - Com o
sys:sys.argv,sys.exite o código de saída,sys.path,sys.versionesys.version_info. - Os erros reais:
FileNotFoundError,FileExistsError,KeyErrore o arquivo seu que "esconde" um módulo do Python.
A ideia: olhar pela janela e olhar no espelho
Quando a Ana chega para trabalhar na padaria, ela faz duas coisas sem pensar. Olha em volta: em qual sala está, o que tem nas prateleiras, se tem algum bilhete na porta. E olha para si mesma: qual é a tarefa do dia, quem pediu, a que horas pode ir embora.
| Módulo | Olha para… | Exemplos de pergunta |
|---|---|---|
os | O sistema, em volta do programa (a janela) | Em qual pasta estou? O que tem nela? Quem é o usuário? |
sys | O Python que está rodando o programa (o espelho) | Com quais argumentos fui chamado? Qual é a minha versão? Como eu termino avisando que deu erro? |
Os dois vêm com o Python; basta o import. Esta aula mostra as partes que um iniciante usa de verdade. Para trabalhar com caminhos de arquivos e pastas, o Python moderno tem um módulo próprio, mais confortável, que ganhou aula só para ele: Pastas e Caminhos (pathlib).
As respostas do os e do sys dependem de onde o programa roda. As janelas de terminal desta aula mostram o computador da Ana (usuária ana, pasta /home/ana, Ubuntu). O editor do guia imita a pasta da Ana (/home/ana), mas é o Python do navegador: lá, o sys.platform é 'emscripten' (e não 'linux'), a versão (3.14.2) e as pastas do sys.path são outras (o sys.executable, não: o editor mostra /usr/bin/python3, como no Ubuntu), e faltam variáveis de ambiente como a EDITOR. As missões desta aula não dependem disso.
1. Em qual pasta estou? os.getcwd() e os.listdir()
Todo programa roda "dentro" de uma pasta, a pasta atual (em inglês, current working directory). É a mesma ideia do pwd do terminal. Quando o programa abre "estoque.csv" sem dizer a pasta, é nela que o Python procura. A Ana tem a pasta da lojinha, com alguns arquivos e uma subpasta fotos, vazia:
import os
print("Estou em:", os.getcwd())
print("Aqui tem:", os.listdir())
print("Em fotos:", os.listdir("fotos"))
$ python3 pasta.py Estou em: /home/ana/loja Aqui tem: ['clientes.json', 'vendas.py', 'pasta.py', 'estoque.csv', 'fotos'] Em fotos: []
- os.getcwd()
- "Pegue a pasta atual" (get current working directory). Devolve o caminho completo, como texto.
- os.listdir()
- "Liste a pasta": uma lista com os nomes do que tem dentro, arquivos e pastas misturados. Sem argumento, lista a pasta atual.
- os.listdir("fotos")
- Com um nome, lista aquela pasta.
[]é a lista vazia: a pasta existe, mas não tem nada.
Repare na ordem: não é alfabética. O os.listdir devolve os nomes na ordem em que o sistema guardou, que pode mudar de um computador para outro. Quando a ordem importa, use sorted(os.listdir()) (aula Ordenando Listas).
A pasta atual é de onde você chamou, não de onde está o arquivo
Agora a Ana roda o mesmo programa, mas a partir da pasta de cima:
$ cd ..
$ python3 loja/pasta.py
Estou em: /home/ana
Aqui tem: ['.bash_history', 'Modelos', '.bash_logout', 'Imagens', '.config', 'Documentos', '.bashrc', 'Público', 'Downloads', 'loja', 'Área de trabalho', 'Vídeos', '.profile', 'Música']
Traceback (most recent call last):
File "/home/ana/loja/pasta.py", line 5, in <module>
print("Em fotos:", os.listdir("fotos"))
~~~~~~~~~~^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'fotos'
A pasta atual agora é /home/ana, porque foi lá que a Ana estava ao chamar o programa. Por isso o listdir() mostrou a pasta pessoal dela (com os arquivos escondidos, que começam com ponto), e o "fotos" não foi encontrado: não existe /home/ana/fotos. Guarde esta regra, que pega muita gente: nomes sem pasta são procurados a partir da pasta atual, e a pasta atual depende de onde o programa foi chamado.
Missão: a pasta deste programa tem quatro arquivos (veja as abas). Mostre só os .csv, em ordem alfabética, no formato CSV: estoque.csv, vendas.csv. Dica: nome.endswith(".csv") (aula Métodos de Texto).
import os nomes = sorted(os.listdir()) print(nomes)
produto,quantidade bolo de cenoura,3
produto,estoque farinha,12
Fechado no feriado.
import os
nomes = sorted(os.listdir())
planilhas = []
for nome in nomes:
if nome.endswith(".csv"):
planilhas.append(nome)
print("CSV:", ", ".join(planilhas))
2. Criar pastas e mudar de pasta: os.mkdir, os.path.exists, os.chdir
import os
print(os.path.exists("relatorios"))
os.mkdir("relatorios")
print(os.path.exists("relatorios"))
os.chdir("relatorios")
print("Agora em:", os.getcwd())
print(os.name, repr(os.sep))
$ python3 mexe.py False True Agora em: /home/ana/loja/relatorios posix '/' $ pwd /home/ana/loja
- os.path.exists("relatorios")
- "O caminho existe?":
TrueouFalse. Antes, não existia; depois domkdir, sim. - os.mkdir("relatorios")
- Cria a pasta (de make directory, como o
mkdirdo terminal). - os.chdir("relatorios")
- Muda a pasta atual do programa (change directory, como o
cd). - os.name
- O "tipo" de sistema:
'posix'no Linux e no macOS,'nt'no Windows. - os.sep
- O separador de pastas:
'/'aqui;'\\'no Windows.
Repare no pwd depois: o terminal continuou em ~/loja. O os.chdir mudou a pasta só do programa, enquanto ele rodava; um programa não consegue mudar a pasta do terminal que o chamou. (É o mesmo motivo de o activate do ambiente virtual precisar do source, na aula venv.)
E se rodar o mesmo programa de novo? A pasta já existe:
$ python3 mexe.py
True
Traceback (most recent call last):
File "/home/ana/loja/mexe.py", line 4, in <module>
os.mkdir("relatorios")
~~~~~~~~^^^^^^^^^^^^^^
FileExistsError: [Errno 17] File exists: 'relatorios'
FileExistsError: "o arquivo já existe" (para o sistema, pasta também é um tipo de arquivo). O os.mkdir não cria por cima. Para "crie se ainda não existir", use os.makedirs("relatorios", exist_ok=True), que também cria as pastas do meio ("relatorios/2026/outubro") de uma vez.
3. Variáveis de ambiente: os.environ
Todo programa recebe do sistema um conjunto de variáveis de ambiente: pares nome → valor que dizem coisas sobre o lugar onde ele está rodando. Quem é o usuário, qual é a pasta pessoal, qual é o idioma. No Python, elas ficam em os.environ, que funciona como um dicionário (aula Dicionários):
import os
print("HOME:", os.environ["HOME"])
print("USER:", os.environ["USER"])
print("LANG:", os.environ["LANG"])
print("EDITOR:", os.environ.get("EDITOR"))
print("LOJA_MODO:", os.environ.get("LOJA_MODO", "normal"))
$ python3 ambiente.py HOME: /home/ana USER: ana LANG: pt_BR.UTF-8 EDITOR: nano LOJA_MODO: normal
| Variável | O que guarda |
|---|---|
HOME | A pasta pessoal do usuário |
USER | O nome do usuário |
LANG | Idioma e codificação: português do Brasil, UTF-8 |
EDITOR | O editor de texto preferido (o nano, aqui) |
PATH | As pastas onde o terminal procura os programas (a que o activate muda) |
- os.environ["HOME"]
- Pega o valor pelo nome, com colchetes. Se a variável não existir, dá erro.
- os.environ.get("EDITOR")
- O
.getdos dicionários: devolve o valor, ouNonese não existir. Sem erro. - os.environ.get("LOJA_MODO", "normal")
- Com um segundo argumento: o valor padrão, quando a variável não existe. A
LOJA_MODOnão existe, então veionormal.
Mandando uma variável para o programa
No terminal, dá para criar uma variável só para um comando, escrevendo NOME=valor antes dele:
$ LOJA_MODO=teste python3 ambiente.py HOME: /home/ana USER: ana LANG: pt_BR.UTF-8 EDITOR: nano LOJA_MODO: teste
É um jeito muito usado de configurar um programa sem mudar o código: modo de teste, endereço de um servidor, uma senha que não pode ficar escrita no arquivo. O programa lê com os.environ.get, e quem chama decide o valor.
Missão: o programa quebra com KeyError, porque a variável LOJA_MODO não existe aqui. Troque os colchetes por .get, com "normal" como valor padrão, para mostrar Modo: normal.
import os
modo = os.environ["LOJA_MODO"]
print("Modo:", modo)
import os
modo = os.environ.get("LOJA_MODO", "normal")
print("Modo:", modo)
4. sys.argv: com o que o programa foi chamado
Você já conheceu o sys.argv na aula argparse: é a lista com o nome do programa e os argumentos que vieram depois dele, todos como texto.
$ python3 -c "import sys; print(sys.argv)" a b ['-c', 'a', 'b']
Com python3 -c, não há arquivo, e o item 0 vira '-c'; com um arquivo, é o nome dele ('ola.py'). Para programas com mais de um ou dois argumentos, prefira o argparse.
5. sys.exit: terminar o programa (e avisar como foi)
Todo programa, ao terminar, devolve ao sistema um número: o código de saída. 0 quer dizer "deu tudo certo"; qualquer outro número quer dizer "deu algum problema". No terminal, echo $? mostra o código do último comando. Quem decide o número é o sys.exit:
import sys
if len(sys.argv) < 2:
print("Uso: python3 saida.py PRODUTO", file=sys.stderr)
sys.exit(1)
print("Procurando", sys.argv[1])
sys.exit(0)
$ python3 saida.py bolo Procurando bolo $ echo $? 0 $ python3 saida.py Uso: python3 saida.py PRODUTO $ echo $? 1
- sys.exit(1)
- Termina o programa ali mesmo, com o código 1. As linhas de baixo não rodam.
- sys.exit(0)
- Termina com "deu certo". No fim do arquivo é opcional: um programa que chega ao fim sem erro já sai com 0.
- file=sys.stderr
- Manda o
printpara a saída de erros (standard error), um segundo canal de saída, separado do normal (sys.stdout). Na tela, os dois aparecem juntos.
Para que dois canais? Para quem chama poder separar. Com 2>/dev/null, o terminal joga fora a saída de erros, e a mensagem de uso some; mas o código 1 continua lá, avisando que algo deu errado:
$ python3 saida.py 2>/dev/null $ echo $? 1
Esse número é o que scripts e outros programas olham para saber se o seu programa funcionou (a aula subprocess mostra o Python fazendo isso).
Formas de chamar o sys.exit
Com um texto em vez de número, o Python mostra o texto na saída de erros e sai com o código 1. É o jeito mais curto de "parar com uma mensagem":
import sys
sys.exit("Erro: o arquivo de estoque não foi encontrado.")
$ python3 saida2.py Erro: o arquivo de estoque não foi encontrado. $ echo $? 1
| Chamada | Código de saída | Quando usar |
|---|---|---|
| (chegar ao fim do programa) | 0 | O normal: deu certo |
sys.exit() ou sys.exit(0) | 0 | Terminar antes do fim, com sucesso |
sys.exit(1), sys.exit(2)… | O número dado | Terminar com erro; cada número pode indicar um tipo de problema (o argparse usa 2 para "chamou errado") |
sys.exit("mensagem") | 1 | Terminar com erro e uma mensagem para a pessoa |
| (uma exceção não tratada) | 1 | O Python mostra o traceback e sai com 1 |
Por dentro: o SystemExit
O sys.exit não "desliga" o Python na hora: ele lança uma exceção, a SystemExit. Se ninguém a pegar, o programa termina. Por isso um try consegue segurá-la:
import sys
try:
sys.exit(3)
except SystemExit as e:
print("Pegou o SystemExit, código", e.code)
print("O programa continuou.")
$ python3 saida3.py Pegou o SystemExit, código 3 O programa continuou. $ echo $? 0
Na prática, você quase nunca faz isso de propósito. O cuidado é o contrário: um except: sem nome, que pega tudo, também engole o sys.exit. Escreva sempre o nome da exceção no except (aula try e except).
Missão: nesta caixa o programa é chamado sem argumentos e quebra com IndexError (código 1). Antes de usar o sys.argv[1], confira: se não veio argumento, mostre Uso: python3 main.py PRODUTO e termine com o código 2.
import sys
produto = sys.argv[1]
print("Procurando", produto)
import sys
if len(sys.argv) < 2:
print("Uso: python3 main.py PRODUTO", file=sys.stderr)
sys.exit(2)
produto = sys.argv[1]
print("Procurando", produto)
6. sys.path: onde o Python procura os módulos
Quando você escreve import random, como o Python sabe onde está o random? Ele procura numa lista de pastas, em ordem, e usa o primeiro que encontrar. A lista é o sys.path:
import sys
for pasta in sys.path:
print(repr(pasta))
$ python3 caminhos.py '/home/ana/loja' '/usr/lib/python314.zip' '/usr/lib/python3.14' '/usr/lib/python3.14/lib-dynload' '/usr/local/lib/python3.14/dist-packages' '/usr/lib/python3/dist-packages'
- '/home/ana/loja'
- A primeira pasta é a do programa. É por isso que um módulo seu, no mesmo lugar, é encontrado (aula Criando seu Módulo).
- '/usr/lib/python3.14'
- A biblioteca padrão:
random.py,json,os.py… - '…/python314.zip', 'lib-dynload'
- Outros lugares da biblioteca padrão (o zip nem existe; o Python só procura nele se existir).
- '…/dist-packages'
- Os pacotes instalados pelo Ubuntu (
apt). Num ambiente virtual, aparece aqui osite-packagesda.venv(aula venv).
O repr() mostra cada texto com as aspas, para que um item vazio ('') também apareça. A pasta do programa vir primeiro é cômodo, mas tem uma armadilha, que está em Quando dá errado.
7. sys.version e sys.version_info: qual Python está rodando
import sys
print(sys.version)
print(sys.version_info)
print(sys.version_info.major, sys.version_info.minor)
print(sys.platform)
print(sys.executable)
if sys.version_info < (3, 12):
print("Este programa precisa do Python 3.12 ou mais novo.")
else:
print("Versão boa.")
$ python3 versao.py 3.14.4 (main, Aug 20 2026, 10:41:58) [GCC 15.2.0] sys.version_info(major=3, minor=14, micro=4, releaselevel='final', serial=0) 3 14 linux /usr/bin/python3 Versão boa.
- sys.version
- Um texto para pessoas lerem: a versão (3.14.4), a data em que esse Python foi compilado e o compilador usado (GCC).
- sys.version_info
- A mesma versão, em partes, para programas usarem:
major(3),minor(14),micro(4) e o estágio ('final'é a versão lançada, não um teste). - sys.version_info < (3, 12)
- Compara com uma tupla (aula Tuplas), parte por parte: 3 com 3, depois 14 com 12. É o jeito certo de conferir a versão.
- sys.platform
- O sistema:
'linux','win32'no Windows,'darwin'no macOS. - sys.executable
- O caminho do Python que está rodando (você usou na aula venv).
sys.version >= "3.9" parece funcionar, mas compara letra por letra: "3.14" é "menor" que "3.9", porque o caractere 1 vem antes do 9. Compare sempre o sys.version_info com uma tupla de números.
Formas diferentes de fazer a mesma coisa
| Tarefa | Com os | Outra forma | Qual usar |
|---|---|---|---|
| Pasta atual | os.getcwd() | Path.cwd() (pathlib) | As duas servem; com pathlib, o resultado já vem pronto para montar caminhos |
| Listar uma pasta | os.listdir("fotos") | Path("fotos").iterdir() | os.listdir para só os nomes; pathlib quando você vai abrir os arquivos |
| Existe? | os.path.exists("x") | Path("x").exists() | Em código novo, pathlib |
| Criar pasta | os.makedirs("a/b", exist_ok=True) | Path("a/b").mkdir(parents=True, exist_ok=True) | Tanto faz; evite o os.mkdir sozinho quando a pasta pode já existir |
| Variável de ambiente | os.environ.get("X", "padrão") | os.environ["X"] | .get, a não ser que o programa não possa rodar sem ela |
| Parar com erro | — | sys.exit("mensagem") ou raise | sys.exit para encerrar o programa; raise dentro de funções (aula raise) |
Quando dá errado
FileNotFoundError: a pasta não existe (ou o programa está em outra pasta)
import os
print(os.listdir("fotografias"))
$ python3 listar.py
Traceback (most recent call last):
File "/home/ana/loja/listar.py", line 3, in <module>
print(os.listdir("fotografias"))
~~~~~~~~~~^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'fotografias'
- File "/home/ana/loja/listar.py", line 3
- O erro foi na linha 3.
- ~~~~~~~~~~^^^^^^^^^^^^^^^
- As marcas apontam a chamada
os.listdir("fotografias"). - FileNotFoundError
- "Arquivo não encontrado".
- [Errno 2] No such file or directory: 'fotografias'
- "Erro número 2 do sistema: não existe arquivo ou pasta com esse nome". O
Errnoé o código que o próprio Linux deu (no editor do guia, que não é Linux, sai[Errno 44]).
A pasta se chama fotos. E lembre do caso da seção 1: o nome pode estar certo e o programa ter sido chamado de outra pasta. Como consertar: confira o nome e confira o os.getcwd().
FileExistsError: criar uma pasta que já existe
Você viu na seção 2: os.mkdir("relatorios") na segunda vez dá FileExistsError: [Errno 17] File exists: 'relatorios'. Como consertar: os.makedirs("relatorios", exist_ok=True), ou teste antes com os.path.exists.
KeyError: a variável de ambiente não existe
import os print(os.environ["LOJA_SENHA"])
$ python3 chave.py
Traceback (most recent call last):
File "/home/ana/loja/chave.py", line 3, in <module>
print(os.environ["LOJA_SENHA"])
~~~~~~~~~~^^^^^^^^^^^^^^
File "<frozen os>", line 709, in __getitem__
KeyError: 'LOJA_SENHA'
O traceback tem duas partes: a linha 3 do seu programa e uma linha File "<frozen os>", que é o código do próprio módulo os ("frozen", "congelado", porque ele vem embutido no Python). O erro aconteceu lá dentro, mas a causa está na sua linha. KeyError: 'LOJA_SENHA' é o mesmo erro de um dicionário sem aquela chave. Como consertar: os.environ.get("LOJA_SENHA"), ou rode com a variável: LOJA_SENHA=... python3 chave.py. Se o programa não tem como funcionar sem ela, uma mensagem clara é melhor que o traceback: sys.exit("Defina a variável LOJA_SENHA.").
A Ana fez um teste numa pasta sorteio e chamou o arquivo de random.py. Depois escreveu o programa do sorteio:
import random print(random.randint(1, 10))
$ python3 sortear.py
Este é o random.py da Ana, não o do Python!
Traceback (most recent call last):
File "/home/ana/sorteio/sortear.py", line 3, in <module>
print(random.randint(1, 10))
^^^^^^^^^^^^^^
AttributeError: module 'random' has no attribute 'randint' (consider renaming '/home/ana/sorteio/random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)
Lembra da ordem do sys.path? A pasta do programa vem primeiro. O import random achou o random.py da Ana antes do random do Python, rodou o print dele e, claro, ali não existe randint. AttributeError: module 'random' has no attribute 'randint' é "o módulo random não tem o atributo randint". E o Python ainda dá a dica entre parênteses: "considere renomear /home/ana/sorteio/random.py, porque ele tem o mesmo nome do módulo random da biblioteca padrão e impede que ele seja importado". Como consertar: renomeie o arquivo (meu_sorteio.py). Nunca dê aos seus arquivos nomes de módulos do Python: random.py, math.py, os.py, json.py, csv.py…
A frase "consider renaming…" apareceu no Python 3.13. Num Python mais antigo, o erro vem só como AttributeError: module 'random' has no attribute 'randint', e você precisa lembrar sozinho dessa armadilha.
Referência rápida
| Código | O que faz |
|---|---|
os.getcwd() | A pasta atual, como texto |
os.chdir("pasta") | Muda a pasta atual do programa |
os.listdir() / os.listdir("pasta") | Lista os nomes (em ordem qualquer; use sorted) |
os.mkdir("pasta") | Cria uma pasta (erro se já existir) |
os.makedirs("a/b", exist_ok=True) | Cria as pastas, se ainda não existirem |
os.path.exists("x") | True se o arquivo ou a pasta existe |
os.environ["NOME"] / os.environ.get("NOME", padrão) | Uma variável de ambiente (com erro / sem erro) |
os.name, os.sep | 'posix' ou 'nt'; '/' ou '\\' |
sys.argv | O programa e os argumentos, como lista de textos |
sys.exit(n) / sys.exit("msg") | Termina com o código n / com a mensagem e o código 1 |
print(..., file=sys.stderr) | Escreve na saída de erros |
sys.path | As pastas onde o import procura, em ordem |
sys.version / sys.version_info | A versão do Python, como texto / em partes |
sys.platform, sys.executable | O sistema; o caminho do Python em uso |
Exercícios
1. A pasta atual
Complete para mostrar a pasta em que o programa está rodando:
2. Sem erro se não existir
Complete para ler a variável LOJA_MODO, com "normal" se ela não existir:
3. Terminar com erro
Que número o sys.exit deve receber para dizer "deu tudo certo"?
4. A Ana roda python3 loja/pasta.py estando em /home/ana. O que os.getcwd() mostra?
5. Por que um arquivo chamado random.py na pasta do programa atrapalha o import random?
6. Qual é o jeito certo de conferir se o Python é o 3.12 ou mais novo?
Missão final: o programa confere antes de começar
Missão: antes de trabalhar, o programa da lojinha confere se as pastas de que precisa existem. A pasta fotos não existe aqui. Para cada nome da lista, se os.path.exists(nome) for falso, termine com sys.exit(f"Faltou a pasta: {nome}"). Se todas existirem, mostre Tudo pronto..
import os
import sys
necessarias = ["fotos", "relatorios"]
for nome in necessarias:
print("Conferindo", nome)
print("Tudo pronto.")
import os
import sys
necessarias = ["fotos", "relatorios"]
for nome in necessarias:
print("Conferindo", nome)
if not os.path.exists(nome):
sys.exit(f"Faltou a pasta: {nome}")
print("Tudo pronto.")
Resumo
osconversa com o sistema;sys, com o próprio Python.os.getcwd()é a pasta atual, que depende de onde o programa foi chamado; nomes sem pasta são procurados a partir dela.os.listdirlista (em ordem qualquer),os.mkdir/os.makedirscriam,os.path.existstesta,os.chdirmuda a pasta só do programa.os.environsão as variáveis de ambiente; prefiraos.environ.get("NOME", padrão).sys.exit(n)termina com o código n (0 = deu certo);sys.exit("msg")mostra a mensagem e sai com 1. Por dentro, é a exceçãoSystemExit.sys.pathé onde oimportprocura, começando pela pasta do programa: não dê aos seus arquivos nomes de módulos do Python.sys.version_info >= (3, 12)confere a versão do jeito certo.