anteriormente pacote pyo3
Construa e publique caixas com ligações pyo3, cffi e uniffi, bem como binários de ferrugem como pacotes python com configuração mínima. Ele suporta a construção de rodas para python 3.8+ no windows, linux, mac e freebsd, pode carregá-los para pypi e tem suporte básico para pypy e graalpy.
Confira o Guia do Usuário!
Você pode baixar binários da versão mais recente ou instalá-los com pipx:
pipx install maturin
Observação
pip install maturin
também deve funcionar se você não quiser usar o pipx.
Existem quatro comandos principais:
maturin new
cria um novo projeto de carga com maturin configurado.maturin publish
constrói a caixa em pacotes python e os publica no pypi.maturin build
constrói as rodas e as armazena em uma pasta ( target/wheels
por padrão), mas não as carrega. É possível fazer upload com barbante ou maturin upload
.maturin develop
constrói a caixa e a instala como um módulo python diretamente no virtualenv atual. Observe que, embora maturin develop
seja mais rápido, ele não oferece suporte a todos os recursos que a execução pip install
após maturin build
suporta. As ligações pyo3
são detectadas automaticamente. Para cffi ou binários, você precisa passar -b cffi
ou -b bin
. maturin não precisa de arquivos de configuração extras e não entra em conflito com uma configuração existente de setuptools-rust ou milksnake. Você pode até integrá-lo com ferramentas de teste como o tox. Existem exemplos para as diferentes ligações na pasta test-crates
.
O nome do pacote será o nome do projeto de carga, ou seja, o campo name na seção [package]
do Cargo.toml
. O nome do módulo que você está usando ao importar será o valor name
na seção [lib]
(cujo padrão é o nome do pacote). Para binários, é simplesmente o nome do binário gerado pela carga.
Ao usar os comandos maturin build
e maturin develop
, você pode compilar um programa com desempenho otimizado adicionando o sinalizador -r
ou --release
.
Os pacotes Python vêm em dois formatos: Um formulário construído chamado roda e distribuições de origem (sdist), ambos arquivos. Uma roda pode ser compatível com qualquer versão python, interpretador (cpython e pypy, principalmente), sistema operacional e arquitetura de hardware (para rodas python puras), pode ser limitada a uma plataforma e arquitetura específica (por exemplo, ao usar ctypes ou cffi) ou para um interpretador python específico e uma versão em uma arquitetura e sistema operacional específicos (por exemplo, com pyo3).
Ao usar pip install
em um pacote, pip tenta encontrar uma roda correspondente e instalá-la. Se não encontrar um, ele baixa a distribuição fonte e constrói uma roda para a plataforma atual, o que requer a instalação dos compiladores corretos. Instalar uma roda é muito mais rápido do que instalar uma distribuição fonte, pois construir rodas geralmente é lento.
Ao publicar um pacote para ser instalado com pip install
, você o carrega no pypi, o repositório oficial de pacotes. Para teste, você pode usar test pypi, que pode ser usado com pip install --index-url https://test.pypi.org/simple/
. Observe que para publicar no Linux, você precisa usar o contêiner docker manylinux, enquanto para publicar a partir do seu repositório você pode usar a ação PyO3/maturin-action do github.
Para pyo3, maturin só pode construir pacotes para versões python instaladas. No Linux e no Mac, todas as versões do Python no PATH
são usadas. Se você não definir seus próprios intérpretes com -i
, uma heurística será usada para procurar instalações python. No Windows, todas as versões do iniciador python (que é instalado por padrão pelo instalador python.org) e todos os ambientes conda, exceto o base, são usados. Você pode verificar quais versões foram selecionadas com o subcomando list-python
.
pyo3 definirá o interpretador python usado na variável de ambiente PYTHON_SYS_EXECUTABLE
, que pode ser usada em scripts de construção personalizados. Maturin pode construir e fazer upload de rodas para pypy com pyo3, embora apenas pypy3.7-7.3 no Linux seja testado.
As rodas Cffi são compatíveis com todas as versões do python, incluindo pypy. Se cffi
não estiver instalado e o python estiver rodando dentro de um virtualenv, o maturin irá instalá-lo, caso contrário você mesmo terá que instalá-lo ( pip install cffi
).
maturin usa cbindgen para gerar um arquivo de cabeçalho, que pode ser personalizado configurando o cbindgen por meio de um arquivo cbindgen.toml
dentro da raiz do seu projeto. Alternativamente, você pode usar um script de construção que grava um arquivo de cabeçalho em $PROJECT_ROOT/target/header.h
.
Com base no arquivo de cabeçalho, o maturin gera um módulo que exporta um ffi
e um objeto lib
.
use cbindgen ;
use std :: env ;
use std :: path :: Path ;
fn main ( ) {
let crate_dir = env :: var ( "CARGO_MANIFEST_DIR" ) . unwrap ( ) ;
let bindings = cbindgen :: Builder :: new ( )
. with_no_includes ( )
. with_language ( cbindgen :: Language :: C )
. with_crate ( crate_dir )
. generate ( )
. unwrap ( ) ;
bindings . write_to_file ( Path :: new ( "target" ) . join ( "header.h" ) ) ;
}
ligações uniffi usam uniffi-rs para gerar ligações ctypes
Python a partir de um arquivo de definição de interface. As rodas uniffi são compatíveis com todas as versões do python, incluindo pypy.
Para criar um projeto misto ferrugem/python, crie uma pasta com o nome do seu módulo (ou seja, lib.name
em Cargo.toml) próximo ao seu Cargo.toml e adicione suas fontes python lá:
my-project
├── Cargo.toml
├── my_project
│ ├── __init__.py
│ └── bar.py
├── pyproject.toml
├── README.md
└── src
└── lib.rs
Você pode especificar um diretório de origem python diferente em pyproject.toml
definindo tool.maturin.python-source
, por exemplo
pyproject.toml
[ tool . maturin ]
python-source = " python "
module-name = " my_project._lib_name "
então a estrutura do projeto ficaria assim:
my-project
├── Cargo.toml
├── python
│ └── my_project
│ ├── __init__.py
│ └── bar.py
├── pyproject.toml
├── README.md
└── src
└── lib.rs
Observação
Esta estrutura é recomendada para evitar uma armadilha comum ImportError
maturin adicionará a extensão nativa como um módulo na sua pasta python. Ao usar o desenvolvimento, o maturin copiará a biblioteca nativa e, para cffi, também o código de cola para sua pasta python. Você deve adicionar esses arquivos ao seu gitignore.
Com cffi você pode fazer from .my_project import lib
e depois usar lib.my_native_function
, com pyo3 você pode diretamente from .my_project import my_native_function
.
Exemplo de layout com pyo3 após maturin develop
:
my-project
├── Cargo.toml
├── my_project
│ ├── __init__.py
│ ├── bar.py
│ └── _lib_name.cpython-36m-x86_64-linux-gnu.so
├── README.md
└── src
└── lib.rs
Ao fazer isso, certifique-se também de definir o nome do módulo em seu código para corresponder à última parte do module-name
(não inclua o caminho do pacote):
# [ pymodule ] # [ pyo3 ( name= "_lib_name" ) ] fn my_lib_name ( _py : Python < ' _ > , m : & PyModule ) -> PyResult < ( ) > { m . add_class :: < MyPythonRustClass > ( ) ? ; Ok ( ( ) ) }
maturin suporta PEP 621, você pode especificar metadados do pacote python em pyproject.toml
. maturin mescla metadados de Cargo.toml
e pyproject.toml
, pyproject.toml
tem precedência sobre Cargo.toml
.
Para especificar dependências python, adicione uma lista de dependencies
em uma seção [project]
no pyproject.toml
. Esta lista é equivalente a install_requires
em setuptools:
[ project ]
name = " my-project "
dependencies = [ " flask~=1.1.0 " , " toml==0.10.0 " ]
Pip permite adicionar os chamados scripts de console, que são comandos shell que executam alguma função em seu programa. Você pode adicionar scripts de console em uma seção [project.scripts]
. As chaves são os nomes dos scripts, enquanto os valores são o caminho para a função no formato some.module.path:class.function
, onde a parte class
é opcional. A função é chamada sem argumentos. Exemplo:
[ project . scripts ]
get_42 = " my_project:DummyClass.get_42 "
Você também pode especificar classificadores trove em seu pyproject.toml
em project.classifiers
:
[ project ]
name = " my-project "
classifiers = [ " Programming Language :: Python " ]
maturin suporta construção por meio de pyproject.toml
. Para usá-lo, crie um pyproject.toml
próximo ao seu Cargo.toml
com o seguinte conteúdo:
[ build-system ]
requires = [ " maturin>=1.0,<2.0 " ]
build-backend = " maturin "
Se um pyproject.toml
com uma entrada [build-system]
estiver presente, maturin poderá construir uma distribuição fonte do seu pacote quando --sdist
for especificado. A distribuição fonte conterá os mesmos arquivos do cargo package
. Para construir apenas uma distribuição fonte, passe --interpreter
sem nenhum valor.
Você pode então, por exemplo, instalar seu pacote com pip install .
. Com pip install . -v
você pode ver a saída de cargo e maturin.
Você pode usar as opções compatibility
, skip-auditwheel
, bindings
, strip
e opções comuns de construção de Cargo, como features
em [tool.maturin]
da mesma forma que faria ao executar maturin diretamente. A chave bindings
é necessária para projetos cffi e bin, pois eles não podem ser detectados automaticamente. Atualmente, todas as compilações estão em modo de lançamento (veja este tópico para detalhes).
Para uma compilação não-manylinux com ligações cffi, você pode usar o seguinte:
[ build-system ]
requires = [ " maturin>=1.0,<2.0 " ]
build-backend = " maturin "
[ tool . maturin ]
bindings = " cffi "
compatibility = " linux "
A opção manylinux
também é aceita como um alias de compatibility
para compatibilidade retroativa com a versão antiga do maturin.
Para incluir arquivos arbitrários no sdist para uso durante a compilação, especifique include
como uma matriz de globs path
com format
definido como sdist
:
[ tool . maturin ]
include = [{ path = " path/**/* " , format = " sdist " }]
Existe um comando maturin sdist
para construir apenas uma distribuição de origem como solução alternativa para pypa/pip#6041.
Por razões de portabilidade, os módulos python nativos no Linux devem vincular dinamicamente apenas um conjunto de poucas bibliotecas que estão instaladas basicamente em todos os lugares, daí o nome manylinux. O pypa oferece imagens docker especiais e uma ferramenta chamada auditwheel para garantir a conformidade com as regras do ManyLinux. Se você deseja publicar rodas amplamente utilizáveis para Linux pypi, você precisa usar uma imagem docker ManyLinux .
O compilador Rust desde a versão 1.64 requer pelo menos glibc 2.17, então você precisa usar pelo menos o manylinux2014. Para publicação, recomendamos aplicar a mesma versão do manylinux que a imagem com o sinalizador manylinux, por exemplo, use --manylinux 2014
se você estiver compilando em quay.io/pypa/manylinux2014_x86_64
. A ação PyO3/maturin-action do github já cuida disso se você definir, por exemplo, manylinux: 2014
.
maturin contém uma reimplementação do auditwheel, verifica automaticamente a biblioteca gerada e fornece ao wheel a tag de plataforma adequada. Se o glibc do seu sistema for muito novo ou você vincular outras bibliotecas compartilhadas, ele atribuirá a tag linux
. Você também pode desativar manualmente essas verificações e usar diretamente o destino nativo do Linux com --manylinux off
.
Para conformidade total com o Manylinux, você precisa compilar em um contêiner Docker CentOS. A imagem pyo3/maturin é baseada na imagem manylinux2014 e passa argumentos para o binário maturin
. Você pode usá-lo assim:
docker run --rm -v $(pwd):/io ghcr.io/pyo3/maturin build --release # or other maturin arguments
Observe que esta imagem é muito básica e contém apenas python, maturin e ferrugem estável. Se precisar de ferramentas adicionais, você pode executar comandos dentro do contêiner manylinux. Consulte konstin/complex-manylinux-maturin-docker para um pequeno exemplo educacional ou nanoporetech/fast-ctc-decode para uma configuração do mundo real.
O próprio maturin é compatível com manylinux quando compilado para o alvo musl.
Todos são bem-vindos para contribuir para o amadurecimento! Existem muitas maneiras de apoiar o projeto, como:
Nossas notas de contribuição têm mais recursos se você deseja doar um tempo voluntário para o amadurecimento e está procurando por onde começar.
Se você não tem tempo para contribuir, mas ainda deseja apoiar o sucesso futuro do projeto, alguns de nossos mantenedores têm páginas de patrocínio no GitHub:
Licenciado sob qualquer um dos seguintes:
a sua opção.