Subscribe to receive notifications of new posts:

Trazer Python para o Workers usando Pyodide e WebAssembly

04/02/2024

17 min read

A partir de hoje, em versão beta aberta, você pode gravar o Cloudflare Workers em Python.

Essa nova compatibilidade com o Python é diferente de como o Workers historicamente era compatível com as linguagens além do JavaScript. Nesse caso, integramos diretamente uma implementação do Python no workerd, o tempo de execução do Workers de código aberto. Todas as vinculações, incluindo vinculações com Vectorize, Workers AI, R2, Durable Objects e muitas outras, são compatíveis desde o primeiro dia. O Python Workers pode importar um subconjunto de pacotes Python populares,  incluindo FastAPI, Langchain, Numpy e muitos mais. Não há etapas extras de desenvolvimento ou cadeias de ferramentas externas.

Para fazer isso, tivemos que ultrapassar os limites de todos os nossos sistemas, desde o próprio tempo de execução, passando pelo nosso sistema de implantação, até o conteúdo do pacote do Worker publicado em nossa rede. Você pode ler os documentos e começar a usar hoje mesmo.

Queremos usar este post para revelar o ciclo de vida interno do Python Worker, compartilhar o que aprendemos no processo e destacar para onde vamos a seguir.

Além de "Basta compilar para WebAssembly"

O Cloudflare Workers é compatível com WebAssembly desde 2018. Cada Worker é um V8 isolado, alimentado pelo mesmo mecanismo JavaScript que o navegador web Chrome. Em princípio, há anos é possível escrever o Workers em qualquer linguagem, incluindo Python, desde que seja compilado primeiro para WebAssembly ou para JavaScript.

Na prática, só porque algo é possível não significa que seja simples. E só porque o "hello world" funciona, não significa que você pode criar um aplicativo com confiança. Desenvolver aplicativos completos requer a compatibilidade com um ecossistema de pacotes com os quais os desenvolvedores estão acostumados a desenvolver. Para que uma plataforma realmente seja compatível com uma linguagem de programação, é necessário ir muito além do que mostrar como compilar código usando cadeias de ferramentas externas.

O Python Workers é diferente do que fizemos no passado. Está no começo e ainda na versão beta, mas achamos que mostra o que é fornecer compatibilidade de primeira classe com linguagens de programação além do JavaScript no Workers.

O ciclo de vida de um Python Worker

Com o Python agora incorporado ao workerd, você pode escrever um Worker assim:

from js import Response

async def on_fetch(request, env):
    return Response.new("Hello world!")

..com um arquivo wrangler.toml que aponta para um  arquivo .py:

name = "hello-world-python-worker"
main = "src/entry.py"
compatibility_date = "2024-03-18"
compatibility_flags = ["python_workers"]

...e quando você executa npx wrangler@latest dev, o tempo de execução do Workers vai:

  1. Determinar qual versão do Pyodide é necessária, com base na data de compatibilidade.
  2. Criar um isolado para seu Worker e injetar o Pyodide automaticamente.
  3. Distribuir seu código Python usando o Pyodide.

Tudo isso acontece de forma oculta, sem a necessidade de qualquer conjunto de ferramentas ou etapas de pré-compilação adicionais. O ambiente de execução do Python é fornecido para você, refletindo como os Workers escritos em JavaScript já funcionam.

Um interpretador Python integrado ao ambiente de execução do Workers

Assim como o JavaScript tem muitos mecanismos, o Python possui muitas implementações que podem executar o código Python. O CPython é a implementação de referência do Python. Se você já usou o Python antes, é quase certo que você usou isso, e é comumente chamado apenas de "Python".

O Pyodide é uma porta do CPython para WebAssembly. Ele interpreta o código Python, sem qualquer necessidade de pré-compilar o próprio código Python para qualquer outro formato. Ele é executado em um navegador web. Confira este REPL. É fiel ao CPython que os desenvolvedores de Python conhecem e esperam, fornecendo a maior parte da biblioteca padrão Python. Ele fornece uma interface de função externa (FFI) para JavaScript, permitindo chamar APIs JavaScript diretamente do Python. Mais sobre isso abaixo.Ele fornece pacotes de código aberto populares e pode importar pacotes Python puros diretamente do Python.

O Pyodide nos pareceu perfeito para o Workers. Ele foi projetado para permitir que o interpretador central e cada módulo nativo do Python sejam construídos como módulos WebAssembly separados, vinculados dinamicamente em tempo de execução. Isso permite que a presença de código para esses módulos seja compartilhada entre todos os Workers em execução na mesma máquina, em vez de exigir que cada Worker traga sua própria cópia. Isso é essencial para fazer o WebAssembly funcionar bem no ambiente do Workers , onde muitas vezes executamos milhares de Workers por máquina. Precisamos que o Workers use a mesma linguagem de programação para compartilhar sua presença de código de tempo de execução. Executar milhares de Workers em cada máquina é o que nos permite implantar todos os aplicativos em todos os locais por um preço razoável.

Assim como no JavaScript Workers, com o Python Workers fornecemos o tempo de execução para você:

Atualmente, o Pyodide é a exceção. A maioria das linguagens que têm como alvo o WebAssembly ainda não é compatível com a vinculação dinâmica, então cada aplicativo acaba trazendo sua própria cópia do tempo de execução de sua linguagem. Esperamos ver mais linguagens compatíveis com links dinâmicos no futuro, para que possamos trazê-las para o Workers de maneira mais eficaz.

Como funciona o Pyodide

O Pyodide executa o código Python em WebAssembly, que é um ambiente de sandbox, separado do tempo de execução do host. Ao contrário da execução de código nativo, todas as operações fora da computação pura (como leituras de arquivos) devem ser fornecidas por um ambiente de tempo de execução e depois importadas pelo módulo WebAssembly.

O LLVM fornece três alvos triplos para o WebAssembly:

  1. wasm32-unknown-unknown – esse back-end não fornece biblioteca C padrão ou interface de chamada de sistema. Para ser compatível com esse back-end, precisaríamos reescrever manualmente cada chamada de sistema ou biblioteca para fazer uso de importações que nós mesmos definimos no tempo de execução.
  2. wasm32-wasi – o WASI é uma interface de sistema padronizada e define um conjunto padrão de importações que são implementadas nos tempos de execução do WASI, como wasmtime.
  3. wasm32-unknown-emscripten – como o WASI, o Emscripten define as importações que um programa WebAssembly precisa executar, mas também gera uma biblioteca JavaScript que implementa essas funções importadas.

O Pyodide usa o Emscripten e fornece três coisas:

  1. Uma distribuição do interpretador CPython, compilada usando Emscripten.
  2. Uma interface de função externa (FFI) entre Python e JavaScript.
  3. Um conjunto de pacotes Python de terceiros, compilado usando o compilador da Emscripten para WebAssembly.

Desses alvos, apenas o Emscripten atualmente oferece suporte à vinculação dinâmica, que, como observamos acima, é essencial para fornecer um tempo de execução de linguagem compartilhado para o Python que é compartilhado entre isolados. O Emscripten faz isso fornecendo implementações de dlopen e dlsym, que usam a biblioteca JavaScript que o acompanha para modificar a tabela do programa WebAssembly para vincular módulos adicionais compilados pelo WebAssembly em tempo de execução. O WASI ainda não é compatível com as abstrações de links dinâmicos dlopen/dlsym usadas pelo CPython.

O Pyodide e a magia das interfaces de funções externas (FFI)

Você deve ter notado que em nosso Hello World Python Worker , importamos  Response  do módulo js :

from js import Response

async def on_fetch(request, env):
    return Response.new("Hello world!")

Por quê?

A maioria dos Workers é escrita em JavaScript e a maior parte do nosso esforço de engenharia no tempo de execução dos Workers é voltada para a melhoria do JavaScript Workers. Há o risco ao adicionar uma segunda linguagem, de que ela nunca alcance a paridade de recursos com a primeira linguagem e sempre considerada sem importância. A interface de função externa (FFI) do Pyodide é fundamental para evitar isso, fornecendo acesso a todas as funcionalidades JavaScript a partir do Python. Isso pode ser usado diretamente pelo autor do Worker e também para fazer com que pacotes como FastAPI e Langchain funcionem imediatamente, como mostraremos mais adiante neste post.

Uma FFI é um sistema para chamar funções em uma linguagem que são implementadas em outra linguagem. Na maioria dos casos, uma FFI é definida por uma linguagem de "nível superior" para chamar funções implementadas em uma linguagem de sistema, geralmente C. O módulo ctypes do Python é um desses sistemas. Esses tipos de interfaces de funções externas costumam ser difíceis de usar devido à natureza das APIs C.

A interface de função externa do Pyodide é uma interface entre Python e JavaScript, que são duas linguagens orientadas a objetos de alto nível com muitas semelhanças de design. Quando passados de uma linguagem para outra, tipos imutáveis, como strings e números, são traduzidos de forma transparente. Todos os objetos mutáveis são agrupados em um proxy apropriado.

Quando um objeto JavaScript é passado para o Python, o Pyodide determina com quais protocolos JavaScript o objeto é compatível e constrói dinamicamente uma classe Python apropriada que implementa os protocolos Python correspondentes. Por exemplo, se o objeto JavaScript for compatível com o protocolo de iteração JavaScript, o proxy será compatível com o protocolo de iteração Python. Se o objeto JavaScript for um Promise ou outro thenable, o objeto Python será um awaitable.

from js import JSON

js_array = JSON.parse("[1,2,3]")

for entry in js_array:
   print(entry)

O ciclo de vida de uma solicitação para um Python Worker faz uso da FFI do Pyodide, agrupando o objeto JavaScript Request recebido em um objeto JsProxy que pode ser acessado em seu código Python. Em seguida, ele converte o valor retornado pelo manipulador do Python Worker em um objeto JavaScript Response que pode ser entregue de volta ao cliente:

O Python vem com uma C FFI, e muitos pacotes Python usam essa FFI para importar bibliotecas nativas. Essas bibliotecas são normalmente escritas em C, portanto, devem primeiro ser compiladas para WebAssembly para funcionar no tempo de execução do Workers. Como observamos acima, o Pyodide é criado com Emscripten, que substitui a C FFI do Python, sempre que um pacote tenta carregar uma biblioteca nativa, ele é carregado a partir de um módulo WebAssembly, fornecido pelo tempo de execução do Workers. A vinculação dinâmica é o que torna isso possível, é o que nos permite substituir a C FFI do Python, permitindo que o Pyodide seja compatível com muitos pacotes Python que possuem dependências de bibliotecas nativas.

A vinculação dinâmica é "paga conforme o uso", enquanto a vinculação estática é "paga antecipadamente", se o código estiver vinculado estaticamente ao seu binário, ele deverá ser carregado antecipadamente para que o binário seja executado, mesmo que esse código nunca seja usado .

A vinculação dinâmica permite que o tempo de execução do Workers compartilhe os módulos WebAssembly subjacentes de pacotes entre diferentes Workers que estão em execução na mesma máquina.

Não vamos entrar muito em detalhes sobre como a vinculação dinâmica funciona no Emscripten, mas a principal conclusão é que o tempo de execução do Emscripten busca módulos WebAssembly de uma abstração de sistema de arquivos fornecida em JavaScript. Para cada Worker, geramos um sistema de arquivos no tempo de execução, cuja estrutura imita uma distribuição Python que tem as dependências do Worker instaladas, mas cujos arquivos subjacentes são compartilhados entre Workers. Isso torna possível compartilhar arquivos Python e WebAssembly entre vários Workers que importam a mesma dependência. Hoje, podemos compartilhar esses arquivos entre Workers, mas copiá-los em cada novo isolado. Acreditamos que podemos ir ainda mais além, empregando técnicas de copy-on-write para compartilhar o recurso subjacente entre muitos Workers.

Compatível com bibliotecas clientes e servidor

O Python tem uma ampla variedade de bibliotecas clientes HTTP populares, incluindo httpx, urllib3, requests e muito mais. Infelizmente, nenhuma delas está pronta para uso no Pyodide. Adicionar suporte para elas tem sido uma das solicitações de usuários mais antigas do projeto Pyodide. Todas as bibliotecas clientes HTTP do Python funcionam com soquetes brutos e o modelo de segurança do navegador e o CORS não permitem isso, então precisávamos de outra maneira de fazê-las funcionar no tempo de execução do Workers.

Bibliotecas clientes assíncronas

Para bibliotecas que podem fazer solicitações de forma assíncrona, incluindo aiohttp e httpx, podemos usar a API Fetch para fazer solicitações. Fazemos isso corrigindo a biblioteca, instruindo-a a usar a API Fetch JavaScript, aproveitando a FFI do Pyodide’. A correção httpx é bastante simples, menos de 100 linhas de código. Simplificando ainda mais, fica assim:

from js import Headers, Request, fetch

def py_request_to_js_request(py_request):
    js_headers = Headers.new(py_request.headers)
    return Request.new(py_request.url, method=py_request.method, headers=js_headers)

def js_response_to_py_response(js_response):
  ... # omitted

async def do_request(py_request):
  js_request = py_request_to_js_request(py_request)
    js_response = await fetch(js_request)
    py_response = js_response_to_py_response(js_response)
    return py_response

Bibliotecas clientes síncronas

Outro desafio da compatibilidade com as bibliotecas clientes HTTP Python é que muitas APIs Python são síncronas. Para essas bibliotecas, não podemos usar a API Fetch diretamente porque ela é assíncrona.

Felizmente, Joe Marshall recentemente fez uma contribuição para a urllib3 que adiciona compatibilidade com o Pyodide em navegadores web ao:

  1. Verificar se é possível bloquear com Atomics.wait()
    a. Em caso afirmativo, iniciar uma busca pelo worker thread
    b. Delegar a operação de busca pelo worker thread e serializar a resposta em um SharedArrayBuffer
    c. No thread Python, use Atomics.wait para bloquear a resposta no SharedArrayBuffer
  2. Se Atomics.wait() não funcionar, volte para um XMLHttpRequest síncrono

Apesar disso, hoje o Cloudflare Workers não é compatível  com worker threads ou XMLHttpRequest síncrono, portanto, nenhuma dessas duas abordagens funcionará no Python Workers. Não somos compatíveis com solicitações síncronas atualmente, mas estamos no caminho...

Comutação de pilhas WebAssembly

Existe uma abordagem que nos permitirá ser compatíveis com solicitações síncronas. O WebAssembly tem uma proposta de estágio 3 adicionando compatibilidade com comutação de pilhas, da qualo v8 tem uma implementação. Os contribuidores do Pyodide têm trabalhado para adicionar suporte para comutação de pilhas ao Pyodide desde setembro de 2022, e o sistema está quase pronto.

Com esse suporte, o Pyodide expõe uma função chamada `run_sync` que pode bloquear a conclusão de um awaitable:

from pyodide.ffi import run_sync

def sync_fetch(py_request):
   js_request = py_request_to_js_request(py_request)
   js_response  = run_sync(fetch(js_request))
   return js_response_to_py_response(js_response)

Asynchronous Server Gateway Interface da FastAPI e do Python

A FastAPI é uma das bibliotecas mais populares para definir servidores Python. Os aplicativos FastAPI usam um protocolo chamado Asynchronous Server Gateway Interface (ASGI). Isso significa que a FastAPI nunca lê ou grava em um soquete propriamente dito. Um aplicativo ASGI espera ser conectado a um servidor ASGI, normalmente uvicorn. O servidor ASGI lida com todos os soquetes brutos em nome do aplicativo.

Para nossa conveniência, isso significa que a FastAPI funciona no Cloudflare Workers sem nenhuma correção ou alterações na próprio FastAPI. Precisamos simplesmente substituir o uvicorn por um servidor ASGI apropriado que possa ser executado em um Worker. A nossa implementação inicial reside aqui, no fork do Pyodide que mantemos. Esperamos adicionar um conjunto de recursos mais abrangente, adicionar cobertura de teste e, em seguida, fazer o upstream dessa implementação no Pyodide.

Você pode tentar fazer isso clonando cloudflare/python-workers-examplese executando `npx wrangler@latest dev` no diretório do exemplo FastAPI.

Importar pacotes Python

O Python Workers é compatível com um subconjunto de pacotes Python, que são fornecidos diretamente pelo Pyodide, incluindo numpy, httpx, FastAPI, Langchaine outros. Isso garante a compatibilidade com o tempo de execução do Pyodide, fixando as versões do pacote nas versões do Pyodide, e permite que o Pyodide corrija implementações internas, como mostramos acima no caso do httpx.

Para importar um pacote, basta adicioná-lo ao seu arquivo requirements.txt, sem adicionar um número de versão. Uma versão específica do pacote é fornecida diretamente pelo Pyodide. Hoje, você pode usar pacotes no desenvolvimento local e, nas próximas semanas, poderá implantar Workers que definem dependências em um arquivo requirements.txt.  Mais adiante neste post, vamos mostrar como estamos pensando em gerenciar novas versões do Pyodide e pacotes.

Mantemos nosso próprio fork do Pyodide, que nos permite fornecer correções específicas para o tempo de execução do Workers e expandir rapidamente nossa compatibilidade com pacotes no Python Workers, ao mesmo tempo que nos comprometemos a fazer o upstream de nossas alterações de volta para o Pyodide, para que todo o ecossistema de desenvolvedores possa se beneficiar.

No entanto, os pacotes Python geralmente são grandes e exigem muita memória, e podem fazer muito trabalho no tempo de importação. Como podemos garantir que você pode trazer os pacotes de que precisa e, ao mesmo tempo, atenuar os longos tempos de inicialização a frio?

Tornando as partidas a frio mais rápidas com instantâneos de memória

No exemplo do início deste post, em desenvolvimento local, mencionamos a injeção de Pyodide no seu Worker. O próprio Pyodide tem 6,4 MB, e os pacotes Python também podem ser bem grandes.

Se simplesmente colocássemos o Pyodide no seu Worker e fizéssemos upload para a Cloudflare, seria um Worker bastante grande para carregar em um novo isolado. As inicializações a frio seriam lentas. Em um computador rápido com uma boa conexão de rede, o Pyodide leva cerca de dois segundos para inicializar em um navegador web , um segundo de tempo de rede e um segundo de tempo de CPU. Não seria aceitável inicializá-lo toda vez que você atualizasse seu código para cada isolamento que seu Worker executasse na rede da Cloudflare.

Em vez disso, quando você executa npx wrangler@latest deploy, acontece o seguinte:

  1. O Wrangler faz upload de seu código Python e seu arquivo requirements.txt na API do Workers
  2. Enviamos seu código Python e seu arquivo requirements.txt para o tempo de execução do Workers para ser validado
  3. Criamos um novo isolado para o seu Worker e injetamos automaticamente o Pyodide mais quaisquer pacotes que você especificou em seu arquivo requirements.txt.
  4. Verificamos o código do Worker em busca de instruções de importação, executamos e, em seguida, tiramos um instantâneo da memória linear WebAssembly do Worker. Na prática, realizamos o caro trabalho de importar pacotes em tempo de implantação, e não em tempo de execução.
  5. Implantamos esse instantâneo junto com o código Python do seu Worker na rede da Cloudflare.
  6. Assim como um JavaScript Worker, executamos o escopo de nível superior do Worker.

Quando uma solicitação chega ao seu Worker, carregamos esse instantâneo e o usamos para inicializar seu Worker de forma isolada, evitando tempo de inicialização caro:

Isso reduz as inicializações a frio de um Python Worker básico para menos de 1 segundo. No entanto, ainda não estamos satisfeitos com isso. Estamos confiantes de que podemos reduzir isso muito, muito mais. Como? Reutilizando instantâneos de memória.

Reutilizar instantâneos de memória

Quando você faz upload de um Python Worker, geramos um único instantâneo de memória das importações de nível superior do Worker, incluindo o Pyodide e quaisquer dependências. Esse instantâneo é específico para seu Worker. Ele não pode ser compartilhado, mesmo que a maior parte de seu conteúdo seja o mesmo de outros Python Workers.

Em vez disso, podemos criar um instantâneo único compartilhado com antecedência e pré-carregá-lo em um pool de isolados "pré-aquecidos". Esses isolados já teriam o tempo de execução do Pyodide carregado e pronto, fazendo com que o Python Worker funcione como um JavaScript Worker. Em ambos os casos, o interpretador subjacente e o ambiente de execução são fornecidos pelo tempo de execução do Workers e estão disponíveis sob demanda sem demora. A única diferença é que, com o Python, o interpretador é executado em WebAssembly, no Worker.

Os instantâneos são um padrão comum entre tempos de execução e ambientes de execução. O Node.js usa instantâneos do V8 para acelerar o tempo de inicialização. Você pode tirar instantâneos de Firecracker microVMs e retomar a execução em um processo diferente. Há muito mais que podemos fazer aqui, não apenas para o Python Workers, mas também no Workers escrito em JavaScript, instantâneos de armazenamento em cache de código compilado a partir do escopo de nível superior e o estado do próprio isolado. Os Workers são tão rápidos e eficientes que até agora não precisamos tirar instantâneos dessa forma, mas achamos que ainda há grandes ganhos de desempenho a serem obtidos.

Esta é a nossa maior alavanca para reduzir os tempos de partida a frio durante o restante de 2024.

Compatibilidade à prova de futuro com versões Pyodide e datas de compatibilidade

Quando você implanta um Worker na Cloudflare, espera que ele continue em execução indefinidamente, mesmo que nunca o atualize novamente. Existem Workers implantados em 2018 que ainda funcionam bem na produção.

Conseguimos isso usando datas de compatibilidade e sinalizadores de compatibilidade, que fornecem mecanismos de aceitação explícitos para novos comportamentos e alterações possivelmente incompatíveis com versões anteriores, sem afetar os Workers existentes.

Isso funciona em parte porque reflete a forma como a internet e os navegadores web funcionam. Você publica uma página web com algum JavaScript e, com razão, espera que funcione para sempre. Os navegadores web e o Cloudflare Workers têm o mesmo tipo de compromisso de estabilidade com os desenvolvedores.

No entanto, há um desafio com o Python. Tanto o Pyodide quanto o CPython são versionados. Versões atualizadas são publicadas regularmente e podem conter alterações importantes. E o Pyodide fornece um conjunto de pacotes integrados, cada um com um número de versão fixo. Isso levanta uma questão: como permitimos que você atualize seu Worker para uma versão mais recente do Pyodide?

A resposta é datas de compatibilidade e sinalizadores de compatibilidade.

Uma nova versão do Python é lançada todos os anos em agosto, e uma nova versão do Pyodide é lançada 6 (seis) meses depois. Quando esta nova versão do Pyodide for publicada, vamos adicioná-la ao Workers protegendo-a atrás de um sinalizador de compatibilidade, que só é ativado após uma data de compatibilidade especificada. Isso nos permite fornecer atualizações continuamente, sem risco de alterações significativas, ampliando o compromisso que assumimos do JavaScript com o Python.

Cada versão do Python tem uma janela de suporte de 5 (cinco) anos. Depois que essa janela de suporte passa para uma determinada versão do Python, as correções de segurança não são mais aplicadas, tornando esta versão insegura. Para mitigar esse risco, ao mesmo tempo em que tentamos nos manter o mais fiéis possível com nosso compromisso de estabilidade e suporte no longo prazo, após cinco anos, qualquer Python Worker ainda em uma versão Python que esteja fora da janela de suporte será automaticamente movido para o próxima versão mais antiga do Python. O Python é uma linguagem madura e estável, por isso esperamos que, na maioria dos casos, seu Python Worker continue funcionando sem problemas. Mas, recomendamos atualizar regularmente a data de compatibilidade do seu Worker para permanecer dentro da janela de suporte.

Entre os lançamentos do Python, também esperamos atualizar e adicionar pacotes Python adicionais, usando o mesmo mecanismo de opção. Um sinalizador de compatibilidade será uma combinação da versão Python e a data de lançamento de um conjunto de pacotes. Por exemplo, python_3.17_packages_2025_03_01.

Como as vinculações funcionam no Python Workers

Mencionamos anteriormente que o Pyodide fornece uma interface de função externa (FFI) para JavaScript, o que significa que você pode usar diretamente objetos, métodos, funções e muito mais em JavaScript, diretamente do Python.

Isso significa que, desde o primeiro dia, todas as APIs vinculadas a outros recursos da Cloudflare são compatíveis com o Cloudflare Workers. O objeto env fornecido pelos manipuladores no Python Workers é um objeto JavaScript para o qual o Pyodide fornece uma API proxy, lidando com traduções de tipos entre linguagens automaticamente.

Por exemplo, para gravar e ler um namespace KV a partir de um Python Worker, você escreveria:

from js import Response

async def on_fetch(request, env):
    await env.FOO.put("bar", "baz")
    bar = await env.FOO.get("bar")
    return Response.new(bar) # returns "baz"

Isso também funciona para APIs da web. Veja como Response é importado do módulo js.  Você pode importar qualquer global do JavaScript desta forma.

Tire esse JavaScript do meu Python!

Você provavelmente está lendo este post porque quer escrever em Python em vez de JavaScript. from js import Response simplesmente não é "Pythonico". Nós sabemos disso e já resolvemos esse desafio antes para outra linguagem (Rust). E achamos que podemos fazer isso ainda melhor para o Python.

Lançamos o workers-rs em 2021 para tornar possível escrever o Workers em Rust. Para cada API JavaScript no Workers, nós, juntamente com colaboradores de código aberto, escrevemos ligações que expõem uma API Rust mais idiomática.

Planejamos fazer o mesmo para o Python Workers, começando com as ligações ao Workers AI e ao Vectorize. Mas enquanto o workers-rs exige que você use e atualize uma dependência externa, as APIs que fornecemos com o Python Workers serão integradas diretamente ao tempo de execução dos Workers. Basta atualizar sua data de compatibilidade e obter as APIs mais recente e mais "Pythonicas".

Não se trata apenas de tornar as vinculações dos recursos na Cloudflare mais "Pythonicas", mas também da compatibilidade com o ecossistema.

Semelhante à forma como recentemente convertemos o workers-rs para usar tipos a partir da caixa http, o que facilita o uso da caixa axum para roteamento, pretendemos fazer o mesmo para o Python Workers. Por exemplo, a biblioteca padrão do Python fornece uma API de soquete bruto, da qual muitos pacotes Python dependem. O Workers já fornece connect(), uma API JavaScript para trabalhar com soquetes brutos. Vemos maneiras de fornecer pelo menos um subconjunto da API de soquete da biblioteca padrão Python no Workers, permitindo que um conjunto mais amplo de pacotes Python funcione no Workers, com menos necessidade de correções.

Mas, em última análise, esperamos dar início a um esforço para criar uma API sem servidor padronizada para o Python. Uma que seja fácil de usar para qualquer desenvolvedor Python e ofereça os mesmos recursos do JavaScript.

Estamos apenas começando com o Python Workers

Fornecer compatibilidade verdadeira com uma nova linguagem de programação é um grande investimento que vai muito além de fazer o "hello world" funcionar. Escolhemos o Python intencionalmente, é a segunda linguagem de programação mais popular depois do JavaScript, e estamos empenhados em continuar melhorando o desempenho e ampliando nossa compatibilidade com pacotes Python.

Somos gratos aos mantenedores do Pyodide e à comunidade Python mais ampla, e adoraríamos saber sua opinião. Entre no canal Python Workers no Discord para desenvolvedores da Cloudflare, ou inicie uma discussão no Github sobre o que você gostaria de ver a seguir e com quais pacotes Python você gostaria que tivéssemos compatibilidade.

We protect entire corporate networks, help customers build Internet-scale applications efficiently, accelerate any website or Internet application, ward off DDoS attacks, keep hackers at bay, and can help you on your journey to Zero Trust.

Visit 1.1.1.1 from any device to get started with our free app that makes your Internet faster and safer.

To learn more about our mission to help build a better Internet, start here. If you're looking for a new career direction, check out our open positions.
Developers (PT)Cloudflare Workers (PT)WebAssembly (PT)Python (PT)Developer Platform (PT)WASM (PT)Developer Week (PT)

Follow on X

Dominik Picheta|@d0m96
Cloudflare|@cloudflare

Related posts

December 18, 2023 2:00 PM

Turnstile se integra con el WAF de Cloudflare para desafiar solicitudes fetch

La edición o creación de un nuevo widget de Turnstile con la opción "Pre-Clearence" activada permite a los clientes de Cloudflare utilizar Turnstile para generar un desafío cuando se carga el código HTML de una página y garantizar que todas las respuestas válidas tengan un token de Turnstile válido....

December 18, 2023 2:00 PM

Integration von Turnstile in die Cloudflare-WAF schützt vor Fetch Requests

Cloudflare-Kunden haben jetzt die Möglichkeit, mit Turnstile beim Laden des HTML-Codes einer Seite eine Aufgabe (Challenge) ausgeben zu lassen und durchzusetzen, dass alle gültigen Antworten über einen gültigen Turnstile-Token verfügen. ...

December 18, 2023 2:00 PM

Integração do Turnstile com o Cloudflare WAF para desafiar solicitações de busca

Ao editar ou criar um novo widget Turnstile com “Pré-autorização” habilitada, os clientes da Cloudflare agora podem usar o Turnstile para emitir um desafio quando o HTML de uma página é carregado e garantir que todas as respostas válidas tenham um token ......