committed by
GitHub
14 changed files with 1559 additions and 9 deletions
@ -27,7 +27,7 @@ jobs: |
|||||
env: |
env: |
||||
GITHUB_CONTEXT: ${{ toJson(github) }} |
GITHUB_CONTEXT: ${{ toJson(github) }} |
||||
run: echo "$GITHUB_CONTEXT" |
run: echo "$GITHUB_CONTEXT" |
||||
- uses: tiangolo/[email protected].0 |
- uses: tiangolo/[email protected].1 |
||||
with: |
with: |
||||
token: ${{ secrets.GITHUB_TOKEN }} |
token: ${{ secrets.GITHUB_TOKEN }} |
||||
config: > |
config: > |
||||
|
@ -0,0 +1,298 @@ |
|||||
|
# Variáveis de Ambiente |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Se você já sabe o que são "variáveis de ambiente" e como usá-las, pode pular esta seção. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Uma variável de ambiente (também conhecida como "**env var**") é uma variável que existe **fora** do código Python, no **sistema operacional**, e pode ser lida pelo seu código Python (ou por outros programas também). |
||||
|
|
||||
|
Variáveis de ambiente podem ser úteis para lidar com **configurações** do aplicativo, como parte da **instalação** do Python, etc. |
||||
|
|
||||
|
## Criar e Usar Variáveis de Ambiente |
||||
|
|
||||
|
Você pode **criar** e usar variáveis de ambiente no **shell (terminal)**, sem precisar do Python: |
||||
|
|
||||
|
//// tab | Linux, macOS, Windows Bash |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
// Você pode criar uma variável de ambiente MY_NAME com |
||||
|
$ export MY_NAME="Wade Wilson" |
||||
|
|
||||
|
// Então você pode usá-la com outros programas, como |
||||
|
$ echo "Hello $MY_NAME" |
||||
|
|
||||
|
Hello Wade Wilson |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows PowerShell |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
// Criar uma variável de ambiente MY_NAME |
||||
|
$ $Env:MY_NAME = "Wade Wilson" |
||||
|
|
||||
|
// Usá-la com outros programas, como |
||||
|
$ echo "Hello $Env:MY_NAME" |
||||
|
|
||||
|
Hello Wade Wilson |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
## Ler Variáveis de Ambiente no Python |
||||
|
|
||||
|
Você também pode criar variáveis de ambiente **fora** do Python, no terminal (ou com qualquer outro método) e depois **lê-las no Python**. |
||||
|
|
||||
|
Por exemplo, você poderia ter um arquivo `main.py` com: |
||||
|
|
||||
|
```Python hl_lines="3" |
||||
|
import os |
||||
|
|
||||
|
name = os.getenv("MY_NAME", "World") |
||||
|
print(f"Hello {name} from Python") |
||||
|
``` |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
O segundo argumento para <a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> é o valor padrão a ser retornado. |
||||
|
|
||||
|
Se não for fornecido, é `None` por padrão, Aqui fornecemos `"World"` como o valor padrão a ser usado. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Então você poderia chamar esse programa Python: |
||||
|
|
||||
|
//// tab | Linux, macOS, Windows Bash |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
// Aqui ainda não definimos a variável de ambiente |
||||
|
$ python main.py |
||||
|
|
||||
|
// Como não definimos a variável de ambiente, obtemos o valor padrão |
||||
|
|
||||
|
Hello World from Python |
||||
|
|
||||
|
// Mas se criarmos uma variável de ambiente primeiro |
||||
|
$ export MY_NAME="Wade Wilson" |
||||
|
|
||||
|
// E então chamar o programa novamente |
||||
|
$ python main.py |
||||
|
|
||||
|
// Agora ele pode ler a variável de ambiente |
||||
|
|
||||
|
Hello Wade Wilson from Python |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows PowerShell |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
// Aqui ainda não definimos a variável de ambiente |
||||
|
$ python main.py |
||||
|
|
||||
|
// Como não definimos a variável de ambiente, obtemos o valor padrão |
||||
|
|
||||
|
Hello World from Python |
||||
|
|
||||
|
// Mas se criarmos uma variável de ambiente primeiro |
||||
|
$ $Env:MY_NAME = "Wade Wilson" |
||||
|
|
||||
|
// E então chamar o programa novamente |
||||
|
$ python main.py |
||||
|
|
||||
|
// Agora ele pode ler a variável de ambiente |
||||
|
|
||||
|
Hello Wade Wilson from Python |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
Como as variáveis de ambiente podem ser definidas fora do código, mas podem ser lidas pelo código e não precisam ser armazenadas (com versão no `git`) com o restante dos arquivos, é comum usá-las para configurações ou **definições**. |
||||
|
|
||||
|
Você também pode criar uma variável de ambiente apenas para uma **invocação específica do programa**, que só está disponível para aquele programa e apenas pela duração dele. |
||||
|
|
||||
|
Para fazer isso, crie-a na mesma linha, antes do próprio programa: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
// Criar uma variável de ambiente MY_NAME para esta chamada de programa |
||||
|
$ MY_NAME="Wade Wilson" python main.py |
||||
|
|
||||
|
// Agora ele pode ler a variável de ambiente |
||||
|
|
||||
|
Hello Wade Wilson from Python |
||||
|
|
||||
|
// A variável de ambiente não existe mais depois |
||||
|
$ python main.py |
||||
|
|
||||
|
Hello World from Python |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Você pode ler mais sobre isso em <a href="https://12factor.net/config" class="external-link" target="_blank">The Twelve-Factor App: Config</a>. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Tipos e Validação |
||||
|
|
||||
|
Essas variáveis de ambiente só podem lidar com **strings de texto**, pois são externas ao Python e precisam ser compatíveis com outros programas e com o resto do sistema (e até mesmo com diferentes sistemas operacionais, como Linux, Windows, macOS). |
||||
|
|
||||
|
Isso significa que **qualquer valor** lido em Python de uma variável de ambiente **será uma `str`**, e qualquer conversão para um tipo diferente ou qualquer validação precisa ser feita no código. |
||||
|
|
||||
|
Você aprenderá mais sobre como usar variáveis de ambiente para lidar com **configurações do aplicativo** no [Guia do Usuário Avançado - Configurações e Variáveis de Ambiente](./advanced/settings.md){.internal-link target=_blank}. |
||||
|
|
||||
|
## Variável de Ambiente `PATH` |
||||
|
|
||||
|
Existe uma variável de ambiente **especial** chamada **`PATH`** que é usada pelos sistemas operacionais (Linux, macOS, Windows) para encontrar programas para executar. |
||||
|
|
||||
|
O valor da variável `PATH` é uma longa string composta por diretórios separados por dois pontos `:` no Linux e macOS, e por ponto e vírgula `;` no Windows. |
||||
|
|
||||
|
Por exemplo, a variável de ambiente `PATH` poderia ter esta aparência: |
||||
|
|
||||
|
//// tab | Linux, macOS |
||||
|
|
||||
|
```plaintext |
||||
|
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin |
||||
|
``` |
||||
|
|
||||
|
Isso significa que o sistema deve procurar programas nos diretórios: |
||||
|
|
||||
|
* `/usr/local/bin` |
||||
|
* `/usr/bin` |
||||
|
* `/bin` |
||||
|
* `/usr/sbin` |
||||
|
* `/sbin` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows |
||||
|
|
||||
|
```plaintext |
||||
|
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 |
||||
|
``` |
||||
|
|
||||
|
Isso significa que o sistema deve procurar programas nos diretórios: |
||||
|
|
||||
|
* `C:\Program Files\Python312\Scripts` |
||||
|
* `C:\Program Files\Python312` |
||||
|
* `C:\Windows\System32` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
Quando você digita um **comando** no terminal, o sistema operacional **procura** o programa em **cada um dos diretórios** listados na variável de ambiente `PATH`. |
||||
|
|
||||
|
Por exemplo, quando você digita `python` no terminal, o sistema operacional procura um programa chamado `python` no **primeiro diretório** dessa lista. |
||||
|
|
||||
|
Se ele o encontrar, então ele o **usará**. Caso contrário, ele continua procurando nos **outros diretórios**. |
||||
|
|
||||
|
### Instalando o Python e Atualizando o `PATH` |
||||
|
|
||||
|
Durante a instalação do Python, você pode ser questionado sobre a atualização da variável de ambiente `PATH`. |
||||
|
|
||||
|
//// tab | Linux, macOS |
||||
|
|
||||
|
Vamos supor que você instale o Python e ele fique em um diretório `/opt/custompython/bin`. |
||||
|
|
||||
|
Se você concordar em atualizar a variável de ambiente `PATH`, o instalador adicionará `/opt/custompython/bin` para a variável de ambiente `PATH`. |
||||
|
|
||||
|
Poderia parecer assim: |
||||
|
|
||||
|
```plaintext |
||||
|
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin |
||||
|
``` |
||||
|
|
||||
|
Dessa forma, ao digitar `python` no terminal, o sistema encontrará o programa Python em `/opt/custompython/bin` (último diretório) e o utilizará. |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows |
||||
|
|
||||
|
Digamos que você instala o Python e ele acaba em um diretório `C:\opt\custompython\bin`. |
||||
|
|
||||
|
Se você disser sim para atualizar a variável de ambiente `PATH`, o instalador adicionará `C:\opt\custompython\bin` à variável de ambiente `PATH`. |
||||
|
|
||||
|
```plaintext |
||||
|
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin |
||||
|
``` |
||||
|
|
||||
|
Dessa forma, quando você digitar `python` no terminal, o sistema encontrará o programa Python em `C:\opt\custompython\bin` (o último diretório) e o utilizará. |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
Então, se você digitar: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ python |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// tab | Linux, macOS |
||||
|
|
||||
|
O sistema **encontrará** o programa `python` em `/opt/custompython/bin` e o executará. |
||||
|
|
||||
|
Seria aproximadamente equivalente a digitar: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ /opt/custompython/bin/python |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows |
||||
|
|
||||
|
O sistema **encontrará** o programa `python` em `C:\opt\custompython\bin\python` e o executará. |
||||
|
|
||||
|
Seria aproximadamente equivalente a digitar: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ C:\opt\custompython\bin\python |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
Essas informações serão úteis ao aprender sobre [Ambientes Virtuais](virtual-environments.md){.internal-link target=_blank}. |
||||
|
|
||||
|
## Conclusão |
||||
|
|
||||
|
Com isso, você deve ter uma compreensão básica do que são **variáveis de ambiente** e como usá-las em Python. |
||||
|
|
||||
|
Você também pode ler mais sobre elas na <a href="https://en.wikipedia.org/wiki/Environment_variable" class="external-link" target="_blank">Wikipedia para Variáveis de Ambiente</a>. |
||||
|
|
||||
|
Em muitos casos, não é muito óbvio como as variáveis de ambiente seriam úteis e aplicáveis imediatamente. Mas elas continuam aparecendo em muitos cenários diferentes quando você está desenvolvendo, então é bom saber sobre elas. |
||||
|
|
||||
|
Por exemplo, você precisará dessas informações na próxima seção, sobre [Ambientes Virtuais](virtual-environments.md). |
@ -0,0 +1,115 @@ |
|||||
|
# Depuração |
||||
|
|
||||
|
Você pode conectar o depurador no seu editor, por exemplo, com o Visual Studio Code ou PyCharm. |
||||
|
|
||||
|
## Chamar `uvicorn` |
||||
|
|
||||
|
Em seu aplicativo FastAPI, importe e execute `uvicorn` diretamente: |
||||
|
|
||||
|
```Python hl_lines="1 15" |
||||
|
{!../../../docs_src/debugging/tutorial001.py!} |
||||
|
``` |
||||
|
|
||||
|
### Sobre `__name__ == "__main__"` |
||||
|
|
||||
|
O objetivo principal de `__name__ == "__main__"` é ter algum código que seja executado quando seu arquivo for chamado com: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ python myapp.py |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
mas não é chamado quando outro arquivo o importa, como em: |
||||
|
|
||||
|
```Python |
||||
|
from myapp import app |
||||
|
``` |
||||
|
|
||||
|
#### Mais detalhes |
||||
|
|
||||
|
Digamos que seu arquivo se chama `myapp.py`. |
||||
|
|
||||
|
Se você executá-lo com: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ python myapp.py |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
então a variável interna `__name__` no seu arquivo, criada automaticamente pelo Python, terá como valor a string `"__main__"`. |
||||
|
|
||||
|
Então, a seção: |
||||
|
|
||||
|
```Python |
||||
|
uvicorn.run(app, host="0.0.0.0", port=8000) |
||||
|
``` |
||||
|
|
||||
|
vai executar. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
Isso não acontecerá se você importar esse módulo (arquivo). |
||||
|
|
||||
|
Então, se você tiver outro arquivo `importer.py` com: |
||||
|
|
||||
|
```Python |
||||
|
from myapp import app |
||||
|
|
||||
|
# Mais um pouco de código |
||||
|
``` |
||||
|
|
||||
|
nesse caso, a variável criada automaticamente dentro de `myapp.py` não terá a variável `__name__` com o valor `"__main__"`. |
||||
|
|
||||
|
Então, a linha: |
||||
|
|
||||
|
```Python |
||||
|
uvicorn.run(app, host="0.0.0.0", port=8000) |
||||
|
``` |
||||
|
|
||||
|
não será executada. |
||||
|
|
||||
|
/// info | "Informação" |
||||
|
|
||||
|
Para mais informações, consulte <a href="https://docs.python.org/3/library/__main__.html" class="external-link" target="_blank">a documentação oficial do Python</a>. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Execute seu código com seu depurador |
||||
|
|
||||
|
Como você está executando o servidor Uvicorn diretamente do seu código, você pode chamar seu programa Python (seu aplicativo FastAPI) diretamente do depurador. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
Por exemplo, no Visual Studio Code, você pode: |
||||
|
|
||||
|
* Ir para o painel "Debug". |
||||
|
* "Add configuration...". |
||||
|
* Selecionar "Python" |
||||
|
* Executar o depurador com a opção "`Python: Current File (Integrated Terminal)`". |
||||
|
|
||||
|
Em seguida, ele iniciará o servidor com seu código **FastAPI**, parará em seus pontos de interrupção, etc. |
||||
|
|
||||
|
Veja como pode parecer: |
||||
|
|
||||
|
<img src="/img/tutorial/debugging/image01.png"> |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
Se você usar o Pycharm, você pode: |
||||
|
|
||||
|
* Abrir o menu "Executar". |
||||
|
* Selecionar a opção "Depurar...". |
||||
|
* Então um menu de contexto aparece. |
||||
|
* Selecionar o arquivo para depurar (neste caso, `main.py`). |
||||
|
|
||||
|
Em seguida, ele iniciará o servidor com seu código **FastAPI**, parará em seus pontos de interrupção, etc. |
||||
|
|
||||
|
Veja como pode parecer: |
||||
|
|
||||
|
<img src="/img/tutorial/debugging/image02.png"> |
@ -0,0 +1,249 @@ |
|||||
|
# Testando |
||||
|
|
||||
|
Graças ao <a href="https://www.starlette.io/testclient/" class="external-link" target="_blank">Starlette</a>, testar aplicativos **FastAPI** é fácil e agradável. |
||||
|
|
||||
|
Ele é baseado no <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, que por sua vez é projetado com base em Requests, por isso é muito familiar e intuitivo. |
||||
|
|
||||
|
Com ele, você pode usar o <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a> diretamente com **FastAPI**. |
||||
|
|
||||
|
## Usando `TestClient` |
||||
|
|
||||
|
/// info | "Informação" |
||||
|
|
||||
|
Para usar o `TestClient`, primeiro instale o <a href="https://www.python-httpx.org" class="external-link" target="_blank">`httpx`</a>. |
||||
|
|
||||
|
Certifique-se de criar um [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e instalá-lo, por exemplo: |
||||
|
|
||||
|
```console |
||||
|
$ pip install httpx |
||||
|
``` |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Importe `TestClient`. |
||||
|
|
||||
|
Crie um `TestClient` passando seu aplicativo **FastAPI** para ele. |
||||
|
|
||||
|
Crie funções com um nome que comece com `test_` (essa é a convenção padrão do `pytest`). |
||||
|
|
||||
|
Use o objeto `TestClient` da mesma forma que você faz com `httpx`. |
||||
|
|
||||
|
Escreva instruções `assert` simples com as expressões Python padrão que você precisa verificar (novamente, `pytest` padrão). |
||||
|
|
||||
|
```Python hl_lines="2 12 15-18" |
||||
|
{!../../../docs_src/app_testing/tutorial001.py!} |
||||
|
``` |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Observe que as funções de teste são `def` normais, não `async def`. |
||||
|
|
||||
|
E as chamadas para o cliente também são chamadas normais, não usando `await`. |
||||
|
|
||||
|
Isso permite que você use `pytest` diretamente sem complicações. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// note | "Detalhes técnicos" |
||||
|
|
||||
|
Você também pode usar `from starlette.testclient import TestClient`. |
||||
|
|
||||
|
**FastAPI** fornece o mesmo `starlette.testclient` que `fastapi.testclient` apenas como uma conveniência para você, o desenvolvedor. Mas ele vem diretamente da Starlette. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Se você quiser chamar funções `async` em seus testes além de enviar solicitações ao seu aplicativo FastAPI (por exemplo, funções de banco de dados assíncronas), dê uma olhada em [Testes assíncronos](../advanced/async-tests.md){.internal-link target=_blank} no tutorial avançado. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Separando testes |
||||
|
|
||||
|
Em uma aplicação real, você provavelmente teria seus testes em um arquivo diferente. |
||||
|
|
||||
|
E seu aplicativo **FastAPI** também pode ser composto de vários arquivos/módulos, etc. |
||||
|
|
||||
|
### Arquivo do aplicativo **FastAPI** |
||||
|
|
||||
|
Digamos que você tenha uma estrutura de arquivo conforme descrito em [Aplicativos maiores](bigger-applications.md){.internal-link target=_blank}: |
||||
|
|
||||
|
``` |
||||
|
. |
||||
|
├── app |
||||
|
│ ├── __init__.py |
||||
|
│ └── main.py |
||||
|
``` |
||||
|
|
||||
|
No arquivo `main.py` você tem seu aplicativo **FastAPI**: |
||||
|
|
||||
|
|
||||
|
```Python |
||||
|
{!../../../docs_src/app_testing/main.py!} |
||||
|
``` |
||||
|
|
||||
|
### Arquivo de teste |
||||
|
|
||||
|
Então você poderia ter um arquivo `test_main.py` com seus testes. Ele poderia estar no mesmo pacote Python (o mesmo diretório com um arquivo `__init__.py`): |
||||
|
|
||||
|
``` hl_lines="5" |
||||
|
. |
||||
|
├── app |
||||
|
│ ├── __init__.py |
||||
|
│ ├── main.py |
||||
|
│ └── test_main.py |
||||
|
``` |
||||
|
|
||||
|
Como esse arquivo está no mesmo pacote, você pode usar importações relativas para importar o objeto `app` do módulo `main` (`main.py`): |
||||
|
|
||||
|
```Python hl_lines="3" |
||||
|
{!../../../docs_src/app_testing/test_main.py!} |
||||
|
``` |
||||
|
|
||||
|
...e ter o código para os testes como antes. |
||||
|
|
||||
|
## Testando: exemplo estendido |
||||
|
|
||||
|
Agora vamos estender este exemplo e adicionar mais detalhes para ver como testar diferentes partes. |
||||
|
|
||||
|
### Arquivo de aplicativo **FastAPI** estendido |
||||
|
|
||||
|
Vamos continuar com a mesma estrutura de arquivo de antes: |
||||
|
|
||||
|
``` |
||||
|
. |
||||
|
├── app |
||||
|
│ ├── __init__.py |
||||
|
│ ├── main.py |
||||
|
│ └── test_main.py |
||||
|
``` |
||||
|
|
||||
|
Digamos que agora o arquivo `main.py` com seu aplicativo **FastAPI** tenha algumas outras **operações de rotas**. |
||||
|
|
||||
|
Ele tem uma operação `GET` que pode retornar um erro. |
||||
|
|
||||
|
Ele tem uma operação `POST` que pode retornar vários erros. |
||||
|
|
||||
|
Ambas as *operações de rotas* requerem um cabeçalho `X-Token`. |
||||
|
|
||||
|
//// tab | Python 3.10+ |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../../docs_src/app_testing/app_b_an_py310/main.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.9+ |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../../docs_src/app_testing/app_b_an_py39/main.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.8+ |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../../docs_src/app_testing/app_b_an/main.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.10+ non-Annotated |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Prefira usar a versão `Annotated` se possível. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../../docs_src/app_testing/app_b_py310/main.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.8+ non-Annotated |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Prefira usar a versão `Annotated` se possível. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../../docs_src/app_testing/app_b/main.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
### Arquivo de teste estendido |
||||
|
|
||||
|
Você pode então atualizar `test_main.py` com os testes estendidos: |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../../docs_src/app_testing/app_b/test_main.py!} |
||||
|
``` |
||||
|
|
||||
|
Sempre que você precisar que o cliente passe informações na requisição e não souber como, você pode pesquisar (no Google) como fazer isso no `httpx`, ou até mesmo como fazer isso com `requests`, já que o design do HTTPX é baseado no design do Requests. |
||||
|
|
||||
|
Depois é só fazer o mesmo nos seus testes. |
||||
|
|
||||
|
Por exemplo: |
||||
|
|
||||
|
* Para passar um parâmetro *path* ou *query*, adicione-o à própria URL. |
||||
|
* Para passar um corpo JSON, passe um objeto Python (por exemplo, um `dict`) para o parâmetro `json`. |
||||
|
* Se você precisar enviar *Dados de Formulário* em vez de JSON, use o parâmetro `data`. |
||||
|
* Para passar *headers*, use um `dict` no parâmetro `headers`. |
||||
|
* Para *cookies*, um `dict` no parâmetro `cookies`. |
||||
|
|
||||
|
Para mais informações sobre como passar dados para o backend (usando `httpx` ou `TestClient`), consulte a <a href="https://www.python-httpx.org" class="external-link" target="_blank">documentação do HTTPX</a>. |
||||
|
|
||||
|
/// info | "Informação" |
||||
|
|
||||
|
Observe que o `TestClient` recebe dados que podem ser convertidos para JSON, não para modelos Pydantic. |
||||
|
|
||||
|
Se você tiver um modelo Pydantic em seu teste e quiser enviar seus dados para o aplicativo durante o teste, poderá usar o `jsonable_encoder` descrito em [Codificador compatível com JSON](encoder.md){.internal-link target=_blank}. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Execute-o |
||||
|
|
||||
|
Depois disso, você só precisa instalar o `pytest`. |
||||
|
|
||||
|
Certifique-se de criar um [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e instalá-lo, por exemplo: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ pip install pytest |
||||
|
|
||||
|
---> 100% |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
Ele detectará os arquivos e os testes automaticamente, os executará e informará os resultados para você. |
||||
|
|
||||
|
Execute os testes com: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ pytest |
||||
|
|
||||
|
================ test session starts ================ |
||||
|
platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 |
||||
|
rootdir: /home/user/code/superawesome-cli/app |
||||
|
plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1 |
||||
|
collected 6 items |
||||
|
|
||||
|
---> 100% |
||||
|
|
||||
|
test_main.py <span style="color: green; white-space: pre;">...... [100%]</span> |
||||
|
|
||||
|
<span style="color: green;">================= 1 passed in 0.03s =================</span> |
||||
|
``` |
||||
|
|
||||
|
</div> |
@ -0,0 +1,844 @@ |
|||||
|
# Ambientes Virtuais |
||||
|
|
||||
|
Ao trabalhar em projetos Python, você provavelmente deve usar um **ambiente virtual** (ou um mecanismo similar) para isolar os pacotes que você instala para cada projeto. |
||||
|
|
||||
|
/// info | "Informação" |
||||
|
|
||||
|
Se você já sabe sobre ambientes virtuais, como criá-los e usá-los, talvez seja melhor pular esta seção. 🤓 |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Um **ambiente virtual** é diferente de uma **variável de ambiente**. |
||||
|
|
||||
|
Uma **variável de ambiente** é uma variável no sistema que pode ser usada por programas. |
||||
|
|
||||
|
Um **ambiente virtual** é um diretório com alguns arquivos. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// info | "Informação" |
||||
|
|
||||
|
Esta página lhe ensinará como usar **ambientes virtuais** e como eles funcionam. |
||||
|
|
||||
|
Se você estiver pronto para adotar uma **ferramenta que gerencia tudo** para você (incluindo a instalação do Python), experimente <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">uv</a>. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Criar um Projeto |
||||
|
|
||||
|
Primeiro, crie um diretório para seu projeto. |
||||
|
|
||||
|
O que normalmente faço é criar um diretório chamado `code` dentro do meu diretório home/user. |
||||
|
|
||||
|
E dentro disso eu crio um diretório por projeto. |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
// Vá para o diretório inicial |
||||
|
$ cd |
||||
|
// Crie um diretório para todos os seus projetos de código |
||||
|
$ mkdir code |
||||
|
// Entre nesse diretório de código |
||||
|
$ cd code |
||||
|
// Crie um diretório para este projeto |
||||
|
$ mkdir awesome-project |
||||
|
// Entre no diretório do projeto |
||||
|
$ cd awesome-project |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
## Crie um ambiente virtual |
||||
|
|
||||
|
Ao começar a trabalhar em um projeto Python **pela primeira vez**, crie um ambiente virtual **<abbr title="existem outras opções, esta é uma diretriz simples">dentro do seu projeto</abbr>**. |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Você só precisa fazer isso **uma vez por projeto**, não toda vez que trabalhar. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
//// tab | `venv` |
||||
|
|
||||
|
Para criar um ambiente virtual, você pode usar o módulo `venv` que vem com o Python. |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ python -m venv .venv |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
/// details | O que esse comando significa |
||||
|
|
||||
|
* `python`: usa o programa chamado `python` |
||||
|
* `-m`: chama um módulo como um script, nós diremos a ele qual módulo vem em seguida |
||||
|
* `venv`: usa o módulo chamado `venv` que normalmente vem instalado com o Python |
||||
|
* `.venv`: cria o ambiente virtual no novo diretório `.venv` |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | `uv` |
||||
|
|
||||
|
Se você tiver o <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a> instalado, poderá usá-lo para criar um ambiente virtual. |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ uv venv |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Por padrão, `uv` criará um ambiente virtual em um diretório chamado `.venv`. |
||||
|
|
||||
|
Mas você pode personalizá-lo passando um argumento adicional com o nome do diretório. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
Esse comando cria um novo ambiente virtual em um diretório chamado `.venv`. |
||||
|
|
||||
|
/// details | `.venv` ou outro nome |
||||
|
|
||||
|
Você pode criar o ambiente virtual em um diretório diferente, mas há uma convenção para chamá-lo de `.venv`. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Ative o ambiente virtual |
||||
|
|
||||
|
Ative o novo ambiente virtual para que qualquer comando Python que você executar ou pacote que você instalar o utilize. |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Faça isso **toda vez** que iniciar uma **nova sessão de terminal** para trabalhar no projeto. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
//// tab | Linux, macOS |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ source .venv/bin/activate |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows PowerShell |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ .venv\Scripts\Activate.ps1 |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows Bash |
||||
|
|
||||
|
Ou se você usa o Bash para Windows (por exemplo, <a href="https://gitforwindows.org/" class="external-link" target="_blank">Git Bash</a>): |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ source .venv/Scripts/activate |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Toda vez que você instalar um **novo pacote** naquele ambiente, **ative** o ambiente novamente. |
||||
|
|
||||
|
Isso garante que, se você usar um **programa de terminal (<abbr title="interface de linha de comando">CLI</abbr>)** instalado por esse pacote, você usará aquele do seu ambiente virtual e não qualquer outro que possa ser instalado globalmente, provavelmente com uma versão diferente do que você precisa. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Verifique se o ambiente virtual está ativo |
||||
|
|
||||
|
Verifique se o ambiente virtual está ativo (o comando anterior funcionou). |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Isso é **opcional**, mas é uma boa maneira de **verificar** se tudo está funcionando conforme o esperado e se você está usando o ambiente virtual pretendido. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
//// tab | Linux, macOS, Windows Bash |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ which python |
||||
|
|
||||
|
/home/user/code/awesome-project/.venv/bin/python |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
Se ele mostrar o binário `python` em `.venv/bin/python`, dentro do seu projeto (neste caso `awesome-project`), então funcionou. 🎉 |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows PowerShell |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ Get-Command python |
||||
|
|
||||
|
C:\Users\user\code\awesome-project\.venv\Scripts\python |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
Se ele mostrar o binário `python` em `.venv\Scripts\python`, dentro do seu projeto (neste caso `awesome-project`), então funcionou. 🎉 |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
## Atualizar `pip` |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Se você usar <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>, você o usará para instalar coisas em vez do `pip`, então não precisará atualizar o `pip`. 😎 |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Se você estiver usando `pip` para instalar pacotes (ele vem por padrão com o Python), você deve **atualizá-lo** para a versão mais recente. |
||||
|
|
||||
|
Muitos erros exóticos durante a instalação de um pacote são resolvidos apenas atualizando o `pip` primeiro. |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Normalmente, você faria isso **uma vez**, logo após criar o ambiente virtual. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Certifique-se de que o ambiente virtual esteja ativo (com o comando acima) e execute: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ python -m pip install --upgrade pip |
||||
|
|
||||
|
---> 100% |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
## Adicionar `.gitignore` |
||||
|
|
||||
|
Se você estiver usando **Git** (você deveria), adicione um arquivo `.gitignore` para excluir tudo em seu `.venv` do Git. |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Se você usou <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a> para criar o ambiente virtual, ele já fez isso para você, você pode pular esta etapa. 😎 |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Faça isso **uma vez**, logo após criar o ambiente virtual. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ echo "*" > .venv/.gitignore |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
/// details | O que esse comando significa |
||||
|
|
||||
|
* `echo "*"`: irá "imprimir" o texto `*` no terminal (a próxima parte muda isso um pouco) |
||||
|
* `>`: qualquer coisa impressa no terminal pelo comando à esquerda de `>` não deve ser impressa, mas sim escrita no arquivo que vai à direita de `>` |
||||
|
* `.gitignore`: o nome do arquivo onde o texto deve ser escrito |
||||
|
|
||||
|
E `*` para Git significa "tudo". Então, ele ignorará tudo no diretório `.venv`. |
||||
|
|
||||
|
Esse comando criará um arquivo `.gitignore` com o conteúdo: |
||||
|
|
||||
|
```gitignore |
||||
|
* |
||||
|
``` |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Instalar Pacotes |
||||
|
|
||||
|
Após ativar o ambiente, você pode instalar pacotes nele. |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Faça isso **uma vez** ao instalar ou atualizar os pacotes que seu projeto precisa. |
||||
|
|
||||
|
Se precisar atualizar uma versão ou adicionar um novo pacote, você **fará isso novamente**. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
### Instalar pacotes diretamente |
||||
|
|
||||
|
Se estiver com pressa e não quiser usar um arquivo para declarar os requisitos de pacote do seu projeto, você pode instalá-los diretamente. |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
É uma (muito) boa ideia colocar os pacotes e versões que seu programa precisa em um arquivo (por exemplo `requirements.txt` ou `pyproject.toml`). |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
//// tab | `pip` |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ pip install "fastapi[standard]" |
||||
|
|
||||
|
---> 100% |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | `uv` |
||||
|
|
||||
|
Se você tem o <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ uv pip install "fastapi[standard]" |
||||
|
---> 100% |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
### Instalar a partir de `requirements.txt` |
||||
|
|
||||
|
Se você tiver um `requirements.txt`, agora poderá usá-lo para instalar seus pacotes. |
||||
|
|
||||
|
//// tab | `pip` |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ pip install -r requirements.txt |
||||
|
---> 100% |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | `uv` |
||||
|
|
||||
|
Se você tem o <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ uv pip install -r requirements.txt |
||||
|
---> 100% |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
/// details | `requirements.txt` |
||||
|
|
||||
|
Um `requirements.txt` com alguns pacotes poderia se parecer com: |
||||
|
|
||||
|
```requirements.txt |
||||
|
fastapi[standard]==0.113.0 |
||||
|
pydantic==2.8.0 |
||||
|
``` |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Execute seu programa |
||||
|
|
||||
|
Depois de ativar o ambiente virtual, você pode executar seu programa, e ele usará o Python dentro do seu ambiente virtual com os pacotes que você instalou lá. |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ python main.py |
||||
|
|
||||
|
Hello World |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
## Configure seu editor |
||||
|
|
||||
|
Você provavelmente usaria um editor. Certifique-se de configurá-lo para usar o mesmo ambiente virtual que você criou (ele provavelmente o detectará automaticamente) para que você possa obter erros de preenchimento automático e em linha. |
||||
|
|
||||
|
Por exemplo: |
||||
|
|
||||
|
* <a href="https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment" class="external-link" target="_blank">VS Code</a> |
||||
|
* <a href="https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html" class="external-link" target="_blank">PyCharm</a> |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Normalmente, você só precisa fazer isso **uma vez**, ao criar o ambiente virtual. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Desativar o ambiente virtual |
||||
|
|
||||
|
Quando terminar de trabalhar no seu projeto, você pode **desativar** o ambiente virtual. |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ deactivate |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
Dessa forma, quando você executar `python`, ele não tentará executá-lo naquele ambiente virtual com os pacotes instalados nele. |
||||
|
|
||||
|
## Pronto para trabalhar |
||||
|
|
||||
|
Agora você está pronto para começar a trabalhar no seu projeto. |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Você quer entender o que é tudo isso acima? |
||||
|
|
||||
|
Continue lendo. 👇🤓 |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Por que ambientes virtuais |
||||
|
|
||||
|
Para trabalhar com o FastAPI, você precisa instalar o <a href="https://www.python.org/" class="external-link" target="_blank">Python</a>. |
||||
|
|
||||
|
Depois disso, você precisará **instalar** o FastAPI e quaisquer outros **pacotes** que queira usar. |
||||
|
|
||||
|
Para instalar pacotes, você normalmente usaria o comando `pip` que vem com o Python (ou alternativas semelhantes). |
||||
|
|
||||
|
No entanto, se você usar `pip` diretamente, os pacotes serão instalados no seu **ambiente Python global** (a instalação global do Python). |
||||
|
|
||||
|
### O Problema |
||||
|
|
||||
|
Então, qual é o problema em instalar pacotes no ambiente global do Python? |
||||
|
|
||||
|
Em algum momento, você provavelmente acabará escrevendo muitos programas diferentes que dependem de **pacotes diferentes**. E alguns desses projetos em que você trabalha dependerão de **versões diferentes** do mesmo pacote. 😱 |
||||
|
|
||||
|
Por exemplo, você pode criar um projeto chamado `philosophers-stone`, este programa depende de outro pacote chamado **`harry`, usando a versão `1`**. Então, você precisa instalar `harry`. |
||||
|
|
||||
|
```mermaid |
||||
|
flowchart LR |
||||
|
stone(philosophers-stone) -->|requires| harry-1[harry v1] |
||||
|
``` |
||||
|
|
||||
|
Então, em algum momento depois, você cria outro projeto chamado `prisoner-of-azkaban`, e esse projeto também depende de `harry`, mas esse projeto precisa do **`harry` versão `3`**. |
||||
|
|
||||
|
```mermaid |
||||
|
flowchart LR |
||||
|
azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] |
||||
|
``` |
||||
|
|
||||
|
Mas agora o problema é que, se você instalar os pacotes globalmente (no ambiente global) em vez de em um **ambiente virtual** local, você terá que escolher qual versão do `harry` instalar. |
||||
|
|
||||
|
Se você quiser executar `philosophers-stone`, precisará primeiro instalar `harry` versão `1`, por exemplo com: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ pip install "harry==1" |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
E então você acabaria com `harry` versão `1` instalado em seu ambiente Python global. |
||||
|
|
||||
|
```mermaid |
||||
|
flowchart LR |
||||
|
subgraph global[global env] |
||||
|
harry-1[harry v1] |
||||
|
end |
||||
|
subgraph stone-project[philosophers-stone project] |
||||
|
stone(philosophers-stone) -->|requires| harry-1 |
||||
|
end |
||||
|
``` |
||||
|
|
||||
|
Mas se você quiser executar `prisoner-of-azkaban`, você precisará desinstalar `harry` versão `1` e instalar `harry` versão `3` (ou apenas instalar a versão `3` desinstalaria automaticamente a versão `1`). |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ pip install "harry==3" |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
E então você acabaria com `harry` versão `3` instalado em seu ambiente Python global. |
||||
|
|
||||
|
E se você tentar executar `philosophers-stone` novamente, há uma chance de que **não funcione** porque ele precisa de `harry` versão `1`. |
||||
|
|
||||
|
```mermaid |
||||
|
flowchart LR |
||||
|
subgraph global[global env] |
||||
|
harry-1[<strike>harry v1</strike>] |
||||
|
style harry-1 fill:#ccc,stroke-dasharray: 5 5 |
||||
|
harry-3[harry v3] |
||||
|
end |
||||
|
subgraph stone-project[philosophers-stone project] |
||||
|
stone(philosophers-stone) -.-x|⛔️| harry-1 |
||||
|
end |
||||
|
subgraph azkaban-project[prisoner-of-azkaban project] |
||||
|
azkaban(prisoner-of-azkaban) --> |requires| harry-3 |
||||
|
end |
||||
|
``` |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
É muito comum em pacotes Python tentar ao máximo **evitar alterações drásticas** em **novas versões**, mas é melhor prevenir do que remediar e instalar versões mais recentes intencionalmente e, quando possível, executar os testes para verificar se tudo está funcionando corretamente. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Agora, imagine isso com **muitos** outros **pacotes** dos quais todos os seus **projetos dependem**. Isso é muito difícil de gerenciar. E você provavelmente acabaria executando alguns projetos com algumas **versões incompatíveis** dos pacotes, e não saberia por que algo não está funcionando. |
||||
|
|
||||
|
Além disso, dependendo do seu sistema operacional (por exemplo, Linux, Windows, macOS), ele pode ter vindo com o Python já instalado. E, nesse caso, provavelmente tinha alguns pacotes pré-instalados com algumas versões específicas **necessárias para o seu sistema**. Se você instalar pacotes no ambiente global do Python, poderá acabar **quebrando** alguns dos programas que vieram com seu sistema operacional. |
||||
|
|
||||
|
## Onde os pacotes são instalados |
||||
|
|
||||
|
Quando você instala o Python, ele cria alguns diretórios com alguns arquivos no seu computador. |
||||
|
|
||||
|
Alguns desses diretórios são os responsáveis por ter todos os pacotes que você instala. |
||||
|
|
||||
|
Quando você executa: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
// Não execute isso agora, é apenas um exemplo 🤓 |
||||
|
$ pip install "fastapi[standard]" |
||||
|
---> 100% |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
Isso fará o download de um arquivo compactado com o código FastAPI, normalmente do <a href="https://pypi.org/project/fastapi/" class="external-link" target="_blank">PyPI</a>. |
||||
|
|
||||
|
Ele também fará o **download** de arquivos para outros pacotes dos quais o FastAPI depende. |
||||
|
|
||||
|
Em seguida, ele **extrairá** todos esses arquivos e os colocará em um diretório no seu computador. |
||||
|
|
||||
|
Por padrão, ele colocará os arquivos baixados e extraídos no diretório que vem com a instalação do Python, que é o **ambiente global**. |
||||
|
|
||||
|
## O que são ambientes virtuais |
||||
|
|
||||
|
A solução para os problemas de ter todos os pacotes no ambiente global é usar um **ambiente virtual para cada projeto** em que você trabalha. |
||||
|
|
||||
|
Um ambiente virtual é um **diretório**, muito semelhante ao global, onde você pode instalar os pacotes para um projeto. |
||||
|
|
||||
|
Dessa forma, cada projeto terá seu próprio ambiente virtual (diretório `.venv`) com seus próprios pacotes. |
||||
|
|
||||
|
```mermaid |
||||
|
flowchart TB |
||||
|
subgraph stone-project[philosophers-stone project] |
||||
|
stone(philosophers-stone) --->|requires| harry-1 |
||||
|
subgraph venv1[.venv] |
||||
|
harry-1[harry v1] |
||||
|
end |
||||
|
end |
||||
|
subgraph azkaban-project[prisoner-of-azkaban project] |
||||
|
azkaban(prisoner-of-azkaban) --->|requires| harry-3 |
||||
|
subgraph venv2[.venv] |
||||
|
harry-3[harry v3] |
||||
|
end |
||||
|
end |
||||
|
stone-project ~~~ azkaban-project |
||||
|
``` |
||||
|
|
||||
|
## O que significa ativar um ambiente virtual |
||||
|
|
||||
|
Quando você ativa um ambiente virtual, por exemplo com: |
||||
|
|
||||
|
//// tab | Linux, macOS |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ source .venv/bin/activate |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows PowerShell |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ .venv\Scripts\Activate.ps1 |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows Bash |
||||
|
|
||||
|
Ou se você usa o Bash para Windows (por exemplo, <a href="https://gitforwindows.org/" class="external-link" target="_blank">Git Bash</a>): |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ source .venv/Scripts/activate |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
Esse comando criará ou modificará algumas [variáveis de ambiente](environment-variables.md){.internal-link target=_blank} que estarão disponíveis para os próximos comandos. |
||||
|
|
||||
|
Uma dessas variáveis é a variável `PATH`. |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
Você pode aprender mais sobre a variável de ambiente `PATH` na seção [Variáveis de ambiente](environment-variables.md#path-environment-variable){.internal-link target=_blank}. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
A ativação de um ambiente virtual adiciona seu caminho `.venv/bin` (no Linux e macOS) ou `.venv\Scripts` (no Windows) à variável de ambiente `PATH`. |
||||
|
|
||||
|
Digamos que antes de ativar o ambiente, a variável `PATH` estava assim: |
||||
|
|
||||
|
//// tab | Linux, macOS |
||||
|
|
||||
|
```plaintext |
||||
|
/usr/bin:/bin:/usr/sbin:/sbin |
||||
|
``` |
||||
|
|
||||
|
Isso significa que o sistema procuraria programas em: |
||||
|
|
||||
|
* `/usr/bin` |
||||
|
* `/bin` |
||||
|
* `/usr/sbin` |
||||
|
* `/sbin` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows |
||||
|
|
||||
|
```plaintext |
||||
|
C:\Windows\System32 |
||||
|
``` |
||||
|
|
||||
|
Isso significa que o sistema procuraria programas em: |
||||
|
|
||||
|
* `C:\Windows\System32` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
Após ativar o ambiente virtual, a variável `PATH` ficaria mais ou menos assim: |
||||
|
|
||||
|
//// tab | Linux, macOS |
||||
|
|
||||
|
```plaintext |
||||
|
/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin |
||||
|
``` |
||||
|
|
||||
|
Isso significa que o sistema agora começará a procurar primeiro por programas em: |
||||
|
|
||||
|
```plaintext |
||||
|
/home/user/code/awesome-project/.venv/bin |
||||
|
``` |
||||
|
|
||||
|
antes de procurar nos outros diretórios. |
||||
|
|
||||
|
Então, quando você digita `python` no terminal, o sistema encontrará o programa Python em |
||||
|
|
||||
|
```plaintext |
||||
|
/home/user/code/awesome-project/.venv/bin/python |
||||
|
``` |
||||
|
|
||||
|
e usa esse. |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows |
||||
|
|
||||
|
```plaintext |
||||
|
C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 |
||||
|
``` |
||||
|
|
||||
|
Isso significa que o sistema agora começará a procurar primeiro por programas em: |
||||
|
|
||||
|
```plaintext |
||||
|
C:\Users\user\code\awesome-project\.venv\Scripts |
||||
|
``` |
||||
|
|
||||
|
antes de procurar nos outros diretórios. |
||||
|
|
||||
|
Então, quando você digita `python` no terminal, o sistema encontrará o programa Python em |
||||
|
|
||||
|
```plaintext |
||||
|
C:\Users\user\code\awesome-project\.venv\Scripts\python |
||||
|
``` |
||||
|
|
||||
|
e usa esse. |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
Um detalhe importante é que ele colocará o caminho do ambiente virtual no **início** da variável `PATH`. O sistema o encontrará **antes** de encontrar qualquer outro Python disponível. Dessa forma, quando você executar `python`, ele usará o Python **do ambiente virtual** em vez de qualquer outro `python` (por exemplo, um `python` de um ambiente global). |
||||
|
|
||||
|
Ativar um ambiente virtual também muda algumas outras coisas, mas esta é uma das mais importantes. |
||||
|
|
||||
|
## Verificando um ambiente virtual |
||||
|
|
||||
|
Ao verificar se um ambiente virtual está ativo, por exemplo com: |
||||
|
|
||||
|
//// tab | Linux, macOS, Windows Bash |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ which python |
||||
|
|
||||
|
/home/user/code/awesome-project/.venv/bin/python |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Windows PowerShell |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ Get-Command python |
||||
|
|
||||
|
C:\Users\user\code\awesome-project\.venv\Scripts\python |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
Isso significa que o programa `python` que será usado é aquele **no ambiente virtual**. |
||||
|
|
||||
|
você usa `which` no Linux e macOS e `Get-Command` no Windows PowerShell. |
||||
|
|
||||
|
A maneira como esse comando funciona é que ele vai e verifica na variável de ambiente `PATH`, passando por **cada caminho em ordem**, procurando pelo programa chamado `python`. Uma vez que ele o encontre, ele **mostrará o caminho** para esse programa. |
||||
|
|
||||
|
A parte mais importante é que quando você chama ``python`, esse é exatamente o "`python`" que será executado. |
||||
|
|
||||
|
Assim, você pode confirmar se está no ambiente virtual correto. |
||||
|
|
||||
|
/// tip | "Dica" |
||||
|
|
||||
|
É fácil ativar um ambiente virtual, obter um Python e então **ir para outro projeto**. |
||||
|
|
||||
|
E o segundo projeto **não funcionaria** porque você está usando o **Python incorreto**, de um ambiente virtual para outro projeto. |
||||
|
|
||||
|
É útil poder verificar qual `python` está sendo usado. 🤓 |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Por que desativar um ambiente virtual |
||||
|
|
||||
|
Por exemplo, você pode estar trabalhando em um projeto `philosophers-stone`, **ativar esse ambiente virtual**, instalar pacotes e trabalhar com esse ambiente. |
||||
|
|
||||
|
E então você quer trabalhar em **outro projeto** `prisoner-of-azkaban`. |
||||
|
|
||||
|
Você vai para aquele projeto: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ cd ~/code/prisoner-of-azkaban |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
Se você não desativar o ambiente virtual para `philosophers-stone`, quando você executar `python` no terminal, ele tentará usar o Python de `philosophers-stone`. |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ cd ~/code/prisoner-of-azkaban |
||||
|
|
||||
|
$ python main.py |
||||
|
|
||||
|
// Erro ao importar o Sirius, ele não está instalado 😱 |
||||
|
Traceback (most recent call last): |
||||
|
File "main.py", line 1, in <module> |
||||
|
import sirius |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
Mas se você desativar o ambiente virtual e ativar o novo para `prisoner-of-askaban`, quando você executar `python`, ele usará o Python do ambiente virtual em `prisoner-of-azkaban`. |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ cd ~/code/prisoner-of-azkaban |
||||
|
|
||||
|
// Você não precisa estar no diretório antigo para desativar, você pode fazer isso de onde estiver, mesmo depois de ir para o outro projeto 😎 |
||||
|
$ deactivate |
||||
|
|
||||
|
// Ative o ambiente virtual em prisoner-of-azkaban/.venv 🚀 |
||||
|
$ source .venv/bin/activate |
||||
|
|
||||
|
// Agora, quando você executar o python, ele encontrará o pacote sirius instalado neste ambiente virtual ✨ |
||||
|
$ python main.py |
||||
|
|
||||
|
Eu juro solenemente 🐺 |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
## Alternativas |
||||
|
|
||||
|
Este é um guia simples para você começar e lhe ensinar como tudo funciona **por baixo**. |
||||
|
|
||||
|
Existem muitas **alternativas** para gerenciar ambientes virtuais, dependências de pacotes (requisitos) e projetos. |
||||
|
|
||||
|
Quando estiver pronto e quiser usar uma ferramenta para **gerenciar todo o projeto**, dependências de pacotes, ambientes virtuais, etc., sugiro que você experimente o <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">uv</a>. |
||||
|
|
||||
|
`uv` pode fazer muitas coisas, ele pode: |
||||
|
|
||||
|
* **Instalar o Python** para você, incluindo versões diferentes |
||||
|
* Gerenciar o **ambiente virtual** para seus projetos |
||||
|
* Instalar **pacotes** |
||||
|
* Gerenciar **dependências e versões** de pacotes para seu projeto |
||||
|
* Certifique-se de ter um conjunto **exato** de pacotes e versões para instalar, incluindo suas dependências, para que você possa ter certeza de que pode executar seu projeto em produção exatamente da mesma forma que em seu computador durante o desenvolvimento, isso é chamado de **bloqueio** |
||||
|
* E muitas outras coisas |
||||
|
|
||||
|
## Conclusão |
||||
|
|
||||
|
Se você leu e entendeu tudo isso, agora **você sabe muito mais** sobre ambientes virtuais do que muitos desenvolvedores por aí. 🤓 |
||||
|
|
||||
|
Saber esses detalhes provavelmente será útil no futuro, quando você estiver depurando algo que parece complexo, mas você saberá **como tudo funciona**. 😎 |
Loading…
Reference in new issue