Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Neste artigo, você cria um módulo de extensão C++ para CPython para calcular uma tangente hiperbólica e chamá-la de código Python. A rotina é implementada primeiro em Python para demonstrar o ganho relativo de desempenho da implementação da mesma rotina em C++.
Módulos de código escritos em C++ (ou C) são comumente usados para estender os recursos de um interpretador Python. Existem três tipos principais de módulos de extensão:
- Módulos aceleradores: habilite o desempenho acelerado. Como Python é uma linguagem interpretada, você pode escrever um módulo acelerador em C++ para obter maior desempenho.
- Módulos wrapper: Exponha interfaces C/C++ existentes ao código Python ou exponha uma API mais semelhante a Python que seja fácil de usar a partir do Python.
-
Módulos de acesso ao sistema de baixo nível: crie módulos de acesso ao sistema para alcançar recursos de nível inferior do
CPythontempo de execução, do sistema operacional ou do hardware subjacente.
Este artigo demonstra duas maneiras de disponibilizar um módulo de extensão C++ para o Python:
- Use as extensões padrão
CPython, conforme descrito na documentação do Python. - Use PyBind11, que recomendamos para C++11 devido à sua simplicidade. Para garantir a compatibilidade, certifique-se de que está a trabalhar com uma das versões mais recentes do Python.
O exemplo completo para este passo a passo está disponível no GitHub em python-samples-vs-cpp-extension.
Pré-requisitos
Visual Studio 2017 ou posterior, com a carga de trabalho de desenvolvimento Python instalada. A carga de trabalho inclui as ferramentas de desenvolvimento nativas do Python, que adicionam a carga de trabalho C++ e criam as ferramentas necessárias para extensões nativas.
Para obter mais informações sobre as opções de instalação, consulte Instalar suporte Python para Visual Studio.
Observação
Quando você instala a carga de trabalho de ciência de dados e aplicativos analíticos , Python e a opção de ferramentas de desenvolvimento nativo Python são instaladas por padrão.
Se você instalar o Python separadamente, certifique-se de selecionar Baixar símbolos de depuração em Opções avançadas no instalador do Python. Essa opção é necessária para você usar a depuração de modo misto entre o código Python e o código nativo.
Criar o aplicativo Python
Siga estas etapas para criar o aplicativo Python.
Crie um novo projeto Python no Visual Studio selecionando Arquivo>Novo>Projeto.
Na caixa de diálogo Criar um novo projeto , procure por python. Selecione o modelo Aplicativo Python e selecione Avançar.
Insira um nome e um local do projeto e selecione Criar.
Visual Studio cria o novo projeto. O projeto é aberto no Gerenciador de Soluções e o arquivo de projeto (.py) é aberto no editor de códigos.
No arquivo .py , cole o código a seguir. Para experimentar alguns dos recursos de edição do Python, tente inserir o código manualmente.
Esse código calcula uma tangente hiperbólica sem usar a biblioteca matemática, e é o que você acelera mais tarde com extensões nativas do Python.
Sugestão
Escreva seu código em Python puro antes de reescrevê-lo em C++. Dessa forma, você pode verificar mais facilmente se seu código Python nativo está correto.
from random import random from time import perf_counter # Change the value of COUNT according to the speed of your computer. # The value should enable the benchmark to complete in approximately 2 seconds. COUNT = 500000 DATA = [(random() - 0.5) * 3 for _ in range(COUNT)] e = 2.7182818284590452353602874713527 def sinh(x): return (1 - (e ** (-2 * x))) / (2 * (e ** -x)) def cosh(x): return (1 + (e ** (-2 * x))) / (2 * (e ** -x)) def tanh(x): tanh_x = sinh(x) / cosh(x) return tanh_x def test(fn, name): start = perf_counter() result = fn(DATA) duration = perf_counter() - start print('{} took {:.3f} seconds\n\n'.format(name, duration)) for d in result: assert -1 <= d <= 1, " incorrect values" if __name__ == "__main__": print('Running benchmarks with COUNT = {}'.format(COUNT)) test(lambda d: [tanh(x) for x in d], '[tanh(x) for x in d] (Python implementation)')Execute o programa selecionando Depurar>Iniciar sem Depuração ou selecione o atalho de teclado Ctrl+F5.
Uma janela de comando é aberta para mostrar a saída do programa.
Na saída, observe a quantidade de tempo relatada para o processo de referência.
Para este passo a passo, o processo de benchmark deve levar aproximadamente 2 segundos.
Conforme necessário, ajuste o valor da variável
COUNTno código para permitir que o benchmark seja concluído em cerca de 2 segundos no seu computador.Execute o programa novamente e confirme se o valor modificado
COUNTproduz o benchmark em cerca de 2 segundos.
Sugestão
Ao executar benchmarks, sempre use a opção Debug>Start without Debugging . Esse método ajuda a evitar a sobrecarga que pode incorrer quando você executa o código dentro do depurador do Visual Studio.
Criar os principais projetos C++
Siga estas etapas para criar dois projetos C++ idênticos, superfastcode e superfastcode2. Mais tarde, você usa uma abordagem diferente em cada projeto para expor o código C++ para Python.
No Gerenciador de Soluções, clique com o botão direito do mouse no nome da solução e selecione Adicionar>Novo Projeto.
Uma solução Visual Studio pode conter projetos Python e C++, que é uma das vantagens de usar o Visual Studio para desenvolvimento Python.
Na caixa de diálogo Adicionar um novo projeto , defina o filtro Idioma como C++ e digite vazio na caixa Pesquisar .
Na lista de resultados do modelo de projeto, selecione Projeto vazio e selecione Avançar.
Na caixa de diálogo Configurar seu novo projeto , digite o nome do projeto:
- Para o primeiro projeto, digite o nome superfastcode.
- Para o segundo projeto, digite o nome superfastcode2.
Selecione Criar.
Certifique-se de repetir essas etapas e criar dois projetos.
Sugestão
Uma abordagem alternativa está disponível quando você tem as ferramentas de desenvolvimento nativas Python instaladas no Visual Studio. Você pode começar com o modelo Python Extension Module , que pré-conclui muitas das etapas descritas neste artigo.
Para o passo a passo neste artigo, começar com um projeto vazio ajuda a demonstrar como construir o módulo de extensão passo a passo. Depois de entender o processo, você pode usar o modelo alternativo para economizar tempo ao escrever suas próprias extensões.
Adicionar arquivo C++ ao projeto
Em seguida, adicione um arquivo C++ a cada projeto.
No Gerenciador de Soluções, expanda o projeto, clique com o botão direito do mouse no nó Arquivos de Origem e selecione Adicionar>Novo Item.
Na lista de modelos de arquivo, selecione Arquivo C++ (.cpp).
Introduza o Nome do ficheiro como module.cpp e, em seguida, selecione Adicionar.
Importante
Certifique-se de que o nome do ficheiro inclui a extensão .cpp . O Visual Studio procura um arquivo com a extensão .cpp para habilitar a exibição das páginas de propriedades do projeto C++.
Na barra de ferramentas, expanda o menu suspenso Configuração e selecione o tipo de configuração de destino:
- Para um tempo de execução Python de 64 bits, ative a configuração x64 .
- Para um Python runtime de 32 bits, ative a configuração Win32.
Certifique-se de repetir essas etapas para ambos os projetos.
Configurar propriedades do projeto
Antes de adicionar código aos novos arquivos C++, configure as propriedades para cada projeto de módulo C++ e teste as configurações para garantir que tudo esteja funcionando.
Você precisa definir as propriedades do projeto para as configurações de compilação de depuração e compilação de lançamento de cada módulo.
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto do módulo C++ (superfastcode ou superfastcode2) e selecione Propriedades.
Configure as propriedades para a compilação de depuração do módulo e, em seguida, configure as mesmas propriedades para a compilação de libertação:
Na parte superior da caixa de diálogo Páginas de propriedades do projeto, configure as seguintes opções de configuração de arquivo:
Para Configuração, selecione Depurar ou Liberar. (Você pode ver essas opções com o prefixo Ativo .)
Para a Plataforma, selecione Ativo (x64) ou Ativo (Win32), dependendo da sua seleção na etapa anterior.
Observação
Ao criar seus próprios projetos, você desejará configurar as configurações de depuração e liberação separadamente, de acordo com seus requisitos específicos de cenário. Neste exercício, você define as configurações para usar uma compilação de versão do CPython. Essa configuração desabilita alguns recursos de depuração do Microsoft Visual C++ Runtime, incluindo asserções. Usar binários de depuração CPython (python_d.exe) requer configurações diferentes.
Defina outras propriedades do projeto conforme descrito na tabela a seguir.
Para alterar um valor de propriedade, insira um valor no campo de propriedade. Para alguns campos, você pode selecionar o valor atual para expandir um menu suspenso de opções ou abrir uma caixa de diálogo para ajudar a definir o valor.
Depois de atualizar os valores em uma guia, selecione Aplicar antes de alternar para uma guia diferente. Essa ação ajuda a garantir que as alterações permaneçam.
Separador e secção Propriedade Valor Propriedades> de configuraçãoGeral Nome do destino Especifique o nome do módulo para se referir a ele a partir do Python em from...importinstruções, como superfastcode. Você usa esse mesmo nome no código C++ quando define o módulo para Python. Para usar o nome do projeto como o nome do módulo, deixe o valor padrão de $<ProjectName>. Parapython_d.exe, adicione_dao final do nome.Tipo de configuração Biblioteca dinâmica (.dll) Propriedades> de configuraçãoAvançado Extensão do arquivo de destino .pyd (Módulo de Extensão Python) C/C++>Geral Diretórios de Inclusão Adicionais Adicione a pasta Python include conforme apropriado para sua instalação (por exemplo, c:\Python36\include). C/C++>Pré-processador Definições do pré-processador Se estiver presente, altere o valor _DEBUG para NDEBUG para corresponder à versão não debug do CPython. Quando utilizar python_d.exe, deixe este valor inalterado. C/C++>Geração de código Biblioteca de execução DLL multi-threaded (/MD) para corresponder à versão de lançamento (sem depuração) do CPython. Quando utilizar python_d.exe, deixe este valor permanecendo como Multi-threaded Debug DLL (/MDd). Verificações básicas de tempo de execução Predefinição Linker>Geral Diretórios de bibliotecas adicionais Adicione a pasta Python libs que contém arquivos .lib , conforme apropriado para sua instalação (por exemplo, c:\Python36\libs). Certifique-se de apontar para a pasta libs que contém arquivos .lib e não para a pasta Lib que contém arquivos .py . Importante
Se a guia C/C++ não for exibida como uma opção para as propriedades do projeto, o projeto não conterá nenhum arquivo de código que o Visual Studio identifique como arquivos de origem C/C++. Essa condição pode ocorrer se você criar um arquivo de origem sem uma extensão de arquivo .c ou .cpp .
Se você inseriu acidentalmente module.coo em vez de module.cpp quando criou o arquivo C++, o Visual Studio cria o arquivo, mas não define o tipo de arquivo como compilador C/C+. Esse tipo de arquivo é necessário para ativar a presença da guia de propriedades C/C++ na caixa de diálogo de propriedades do projeto. A identificação incorreta permanece mesmo se você renomear o arquivo de código com uma extensão de arquivo .cpp .
Para definir o tipo de arquivo de código corretamente, no Gerenciador de Soluções, clique com o botão direito do mouse no arquivo de código e selecione Propriedades. Para o Tipo de Item, selecione Compilador C/C++.
Depois de atualizar todas as propriedades, selecione OK.
Repita as etapas para a outra configuração de compilação.
Teste sua configuração atual. Repita as etapas a seguir para as compilações de depuração e versão de ambos os projetos C++.
Adicionar código e testar configuração
Agora você está pronto para adicionar código aos seus arquivos C++ e testar a compilação da versão .
Para o projeto C++ superfastcode , abra o arquivo module.cpp no editor de código.
No arquivo module.cpp , cole o seguinte código:
#include <Windows.h> #include <cmath> const double e = 2.7182818284590452353602874713527; double sinh_impl(double x) { return (1 - pow(e, (-2 * x))) / (2 * pow(e, -x)); } double cosh_impl(double x) { return (1 + pow(e, (-2 * x))) / (2 * pow(e, -x)); } double tanh_impl(double x) { return sinh_impl(x) / cosh_impl(x); }Salve suas alterações.
Crie a configuração de versão para o projeto C++ para confirmar que seu código está correto.
Repita as etapas para adicionar código ao arquivo C++ para o projeto superfastcode2 e teste a compilação da versão .
Converter projetos C++ em extensões Python
Para tornar a DLL C++ uma extensão para Python, primeiro modifique os métodos exportados para interagir com tipos Python. Em seguida, adicione uma função para exportar o módulo, juntamente com definições para os métodos do módulo.
As seções a seguir demonstram como criar as extensões usando as extensões CPython e PyBind11. O projeto superfasctcode usa as extensões CPython e o projeto superfasctcode2 implementa PyBind11.
Usar extensões CPython
Para obter mais informações sobre o código apresentado nesta seção, consulte Manual de referência da API Python/C, especialmente a página Module Objects . Ao revisar o conteúdo de referência, certifique-se de selecionar sua versão do Python na lista suspensa no canto superior direito.
Para o projeto C++ superfastcode , abra o arquivo module.cpp no editor de código.
Adicione uma instrução na parte superior do arquivo module.cpp para incluir o arquivo de cabeçalho Python.h :
#include <Python.h>Substitua o código do
tanh_implmétodo para aceitar e retornar tipos Python (ou seja, umPyObject*):PyObject* tanh_impl(PyObject* /* unused module reference */, PyObject* o) { double x = PyFloat_AsDouble(o); double tanh_x = sinh_impl(x) / cosh_impl(x); return PyFloat_FromDouble(tanh_x); }No final do arquivo, adicione uma estrutura para definir como apresentar a função C++
tanh_implao Python:static PyMethodDef superfastcode_methods[] = { // The first property is the name exposed to Python, fast_tanh // The second is the C++ function with the implementation // METH_O means it takes a single PyObject argument { "fast_tanh", (PyCFunction)tanh_impl, METH_O, nullptr }, // Terminate the array with an object containing nulls { nullptr, nullptr, 0, nullptr } };Adicione outra estrutura para definir como se referir ao módulo em seu código Python, especificamente quando você usa a
from...importinstrução.O nome importado neste código deve corresponder ao valor nas propriedades do projeto em Configuration Properties>General>Target Name.
No exemplo a seguir, o
"superfastcode"nome significa que você pode usar afrom superfastcode import fast_tanhinstrução em Python porquefast_tanhé definido dentro desuperfastcode_methods. Os nomes de arquivo que são internos ao projeto C++, como module.cpp, são inconsequentes.static PyModuleDef superfastcode_module = { PyModuleDef_HEAD_INIT, "superfastcode", // Module name to use with Python import statements "Provides some functions, but faster", // Module description 0, superfastcode_methods // Structure that defines the methods of the module };Adicione um método que o Python chama quando carrega o módulo. O nome do método deve ser
PyInit_<module-name>, onde <module-name> corresponde exatamente à propriedade Configuration Properties>General>Target Name do projeto C++. Ou seja, o nome do método corresponde ao nome do arquivo .pyd criado pelo projeto.PyMODINIT_FUNC PyInit_superfastcode() { return PyModule_Create(&superfastcode_module); }Crie o projeto C++ e verifique seu código. Se você encontrar erros, consulte a seção "Solucionar problemas de erros de compilação".
Use PyBind11
Se concluir as etapas na seção anterior para o projeto superfastcode, poderá notar que o exercício requer código padrão para criar as estruturas de módulo para extensões C++ CPython. Neste exercício, você descobre que o PyBind11 simplifica o processo de codificação. Você usa macros em um arquivo de cabeçalho C++ para obter o mesmo resultado, mas com muito menos código. No entanto, etapas adicionais são necessárias para garantir que o Visual Studio possa localizar as bibliotecas PyBind11 e incluir arquivos. Para obter mais informações sobre o código nesta seção, consulte Noções básicas do PyBind11.
Instalar o PyBind11
O primeiro passo é instalar o PyBind11 na configuração do seu projeto. Neste exercício, você usa a janela do Developer PowerShell .
Abra a janela Tools>Command Line>Developer PowerShell .
Na janela do Developer PowerShell , instale o PyBind11 usando o comando
pip install pybind11pip oupy -m pip install pybind11.Visual Studio instala PyBind11 e seus pacotes dependentes.
Adicionar caminhos PyBind11 ao projeto
Após a instalação do PyBind11, você precisa adicionar os caminhos PyBind11 à propriedade Additional Include Directories do projeto.
Na janela do Developer PowerShell , execute o comando
python -m pybind11 --includesoupy -m pybind11 --includes.Esta ação imprime uma lista de caminhos PyBind11 que você precisa adicionar às propriedades do projeto.
Realce a lista de caminhos na janela e selecione Copiar (página dupla) na barra de ferramentas da janela.
A lista de caminhos concatenados é adicionada à área de transferência.
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto superfastcode2 e selecione Propriedades.
Na parte superior da caixa de diálogo Páginas de propriedades , para o campo Configuração , selecione Liberar. (Você pode ver essa opção com o prefixo Ativo .)
Na caixa de diálogo, na guia C/C++>General , expanda o menu suspenso da propriedade Additional Include Directories e selecione Editar.
Na caixa de diálogo pop-up, adicione a lista de caminhos copiados:
Repita estas etapas para cada caminho na lista concatenada copiada da janela do Developer PowerShell :
Selecione Nova linha (pasta com símbolo de adição) na barra de ferramentas da caixa de diálogo pop-up.
O Visual Studio adiciona uma linha vazia na parte superior da lista de caminhos e posiciona o cursor de inserção no início.
Cole o caminho PyBind11 na linha vazia.
Você também pode selecionar Mais opções(...) e usar uma caixa de diálogo pop-up do explorador de arquivos para navegar até o local do caminho.
Importante
- Se o caminho contiver o prefixo
-I, remova-o do caminho. - Para que o Visual Studio reconheça um caminho, o caminho precisa estar em uma linha separada.
Depois de adicionar um novo caminho, o Visual Studio mostra o caminho confirmado no campo Valor avaliado .
- Se o caminho contiver o prefixo
Selecione OK para sair da caixa de diálogo pop-up.
Na parte superior da caixa de diálogo Property Pages , passe o mouse sobre o valor da propriedade Additional Include Directories e confirme se os caminhos PyBind11 estão presentes.
Selecione OK para aplicar as alterações de propriedade.
Atualizar o arquivo module.cpp
A última etapa é adicionar o arquivo de cabeçalho PyBind11 e o código de macro ao arquivo C++ do projeto.
Para o projeto superfastcode2 C++, abra o arquivo module.cpp no editor de códigos.
Adicione uma instrução na parte superior do arquivo module.cpp para incluir o arquivo de cabeçalho pybind11.h :
#include <pybind11/pybind11.h>No final do arquivo de module.cpp , adicione código para a
PYBIND11_MODULEmacro para definir o ponto de entrada para a função C++:namespace py = pybind11; PYBIND11_MODULE(superfastcode2, m) { m.def("fast_tanh2", &tanh_impl, R"pbdoc( Compute a hyperbolic tangent of a single argument expressed in radians. )pbdoc"); #ifdef VERSION_INFO m.attr("__version__") = VERSION_INFO; #else m.attr("__version__") = "dev"; #endif }Crie o projeto C++ e verifique seu código. Se você encontrar erros, consulte a próxima seção, Solucionar problemas de erros de compilação.
Solucionar problemas de erros de compilação
Analise as seções a seguir para verificar possíveis problemas que podem fazer com que a compilação do módulo C++ falhe.
Erro: Não é possível localizar o arquivo de cabeçalho
Visual Studio retorna uma mensagem de erro como E1696: Não é possível abrir o arquivo de origem "Python.h" ou C1083: Não é possível abrir o arquivo de inclusão: "Python.h": Não há tal arquivo ou diretório.
Este erro indica que o compilador não pode localizar um arquivo de cabeçalho (.h) necessário para o seu projeto.
Para o projeto superfastcode , verifique se a propriedade do projeto C/C++>General>Additional Include Directories contém o caminho para a pasta include para sua instalação do Python. Analise as etapas em Configurar propriedades do projeto.
Para o projeto superfastcode2 , verifique se a mesma propriedade do projeto contém o caminho para a pasta include para sua instalação PyBind11. Analise os passos para adicionar caminhos do PyBind ao projeto.
Para obter mais informações sobre como acessar as informações de configuração de instalação do Python, consulte a documentação do Python.
Erro: Não é possível localizar bibliotecas Python
Visual Studio retorna um erro indicando que o compilador não pode localizar os arquivos de biblioteca (DLL) necessários para seu projeto.
- Para o projeto C++ (superfastcode ou superfastcode2), verifique se a propriedade Linker>General>Additional Library Directories contém o caminho para a pasta libs para sua instalação do Python. Analise as etapas em Configurar propriedades do projeto.
Para obter mais informações sobre como acessar as informações de configuração de instalação do Python, consulte a documentação do Python.
Erros do vinculador relacionados à arquitetura de destino
Visual Studio relata erros de vinculador relacionados à configuração de arquitetura de destino para seu projeto, como x64 ou Win32.
- Para o projeto C++ (superfastcode ou superfastcode2), altere a configuração de destino para corresponder à sua instalação do Python. Por exemplo, se a configuração de destino do projeto C++ for Win32, mas a instalação do Python for de 64 bits, altere a configuração de destino do projeto C++ para x64.
Teste o código e compare os resultados
Agora que você tem as DLLs estruturadas como extensões Python, você pode consultá-las a partir do projeto Python, importar os módulos e usar seus métodos.
Disponibilize sua DLL para Python
Você pode disponibilizar sua DLL para Python de várias maneiras. Aqui estão duas opções a considerar:
Se seu projeto Python e projeto C++ estiverem na mesma solução, você pode usar a seguinte abordagem:
No Gerenciador de Soluções, clique com o botão direito do mouse no nó Referências em seu projeto Python e selecione Adicionar Referência.
Certifique-se de fazer essa ação para seu projeto Python e não para seu projeto C++.
Na caixa de diálogo Adicionar referência , expanda a guia Projetos .
Marque as caixas de seleção para os projetos superfastcode e superfastcode2 e selecione OK.
Uma abordagem alternativa é instalar o módulo de extensão C++ em seu ambiente Python. Este método torna o módulo disponível para outros projetos Python. Para obter mais informações, consulte a documentação do projeto setuptools.
Conclua as seguintes etapas para instalar o módulo de extensão C++ em seu ambiente Python:
No Gerenciador de Soluções, clique com o botão direito do mouse em seu projeto C++ e selecione Adicionar>Novo Item.
Na lista de modelos de arquivo, selecione Arquivo C++ (.cpp).
Introduza o Nome do ficheiro como setup.py e, em seguida, selecione Adicionar.
Certifique-se de inserir o nome do arquivo com a extensão Python (.py). O Visual Studio reconhece o arquivo como código Python apesar do uso do modelo de arquivo C++.
O Visual Studio abre o novo arquivo no editor de códigos.
Cole o código a seguir no novo arquivo. Escolha a versão do código que corresponde ao seu método de extensão:
Extensões CPython (projeto superfastcode ):
from setuptools import setup, Extension sfc_module = Extension('superfastcode', sources = ['module.cpp']) setup( name='superfastcode', version='1.0', description='Python Package with superfastcode C++ extension', ext_modules=[sfc_module] )PyBind11 (projeto superfastcode2 ):
from setuptools import setup, Extension import pybind11 cpp_args = ['-std=c++11', '-stdlib=libc++', '-mmacosx-version-min=10.7'] sfc_module = Extension( 'superfastcode2', sources=['module.cpp'], include_dirs=[pybind11.get_include()], language='c++', extra_compile_args=cpp_args, ) setup( name='superfastcode2', version='1.0', description='Python package with superfastcode2 C++ extension (PyBind11)', ext_modules=[sfc_module], )
No projeto C++, crie um segundo arquivo chamado pyproject.toml e cole o seguinte código:
[build-system] requires = ["setuptools", "wheel", "pybind11"] build-backend = "setuptools.build_meta"O arquivo TOML (.toml) usa o formato Tom's Obvious, Minimal Language para arquivos de configuração.
Para criar a extensão, clique com o botão direito do mouse no nome do arquivo pyproject.toml na guia da janela de código e selecione Copiar caminho completo.
Você exclui o nome pyproject.toml do caminho antes de usá-lo.
No Explorador de Soluções, expanda o nó Ambientes Python para a solução.
Clique com o botão direito do mouse no ambiente Python ativo (mostrado em negrito) e selecione Gerenciar pacotes Python.
O painel Ambientes Python é aberto.
Se o pacote necessário já estiver instalado, você o verá listado neste painel.
- Antes de continuar, selecione o X ao lado do nome do pacote para desinstalá-lo.
Na caixa de pesquisa do painel Ambientes Python , cole o caminho copiado e exclua o nome do arquivo pyproject.toml do final do caminho.
Selecione Enter para instalar o módulo a partir do local do caminho copiado.
Sugestão
Se a instalação falhar devido a um erro de permissão, adicione o
--userargumento ao final do comando e tente a instalação novamente.
Chame a DLL a partir do Python
Depois de disponibilizar a DLL para o Python, conforme descrito na seção anterior, pode então chamar as funções superfastcode.fast_tanh e superfastcode2.fast_tanh2 do Python. Em seguida, você pode comparar o desempenho da função com a implementação do Python.
Siga estas etapas para chamar a DLL do módulo de extensão em Python:
Abra o arquivo .py para seu projeto Python no editor de código.
No final do arquivo, adicione o seguinte código para chamar os métodos exportados das DLLs e exibir sua saída:
from superfastcode import fast_tanh test(lambda d: [fast_tanh(x) for x in d], '[fast_tanh(x) for x in d] (CPython C++ extension)') from superfastcode2 import fast_tanh2 test(lambda d: [fast_tanh2(x) for x in d], '[fast_tanh2(x) for x in d] (PyBind11 C++ extension)')Execute o programa Python selecionando Depurar>Iniciar Sem Depuração ou use o atalho de teclado Ctrl+F5.
Observação
Se o comando Iniciar sem Depuração não estiver disponível, no Gerenciador de Soluções, clique com o botão direito do mouse no projeto Python e selecione Definir como Projeto de Inicialização.
Quando o programa é executado, observe que as rotinas C++ são executadas aproximadamente 5 a 20 vezes mais rápido do que a implementação do Python.
Aqui está um exemplo de saída típica do programa:
Running benchmarks with COUNT = 500000 [tanh(x) for x in d] (Python implementation) took 0.758 seconds [fast_tanh(x) for x in d] (CPython C++ extension) took 0.076 seconds [fast_tanh2(x) for x in d] (PyBind11 C++ extension) took 0.204 secondsTente aumentar a
COUNTvariável para que as diferenças de tempo sejam mais pronunciadas.Uma compilação de depuração do módulo C++ também é executada mais lentamente do que uma compilação de lançamento porque a compilação de depuração é menos otimizada e contém várias verificações de erro. Tente alternar entre as configurações de compilação para comparação, mas lembre-se de atualizar as propriedades definidas anteriormente para a configuração de versão.
Reduza a velocidade e a sobrecarga do processo
Na saída, você pode notar que a extensão PyBind11 não é tão rápida quanto a extensão CPython, embora deva ser mais rápida do que a implementação Python pura. A principal razão para a diferença é por causa do uso da bandeira METH_O. Este sinalizador não suporta vários parâmetros, nomes de parâmetros ou argumentos de palavras-chave. O PyBind11 gera um código um pouco mais complexo para fornecer uma interface mais parecida com Python para chamadores. Como o código de teste chama a função 500.000 vezes, os resultados podem amplificar significativamente a sobrecarga.
Você pode reduzir ainda mais a sobrecarga movendo o for loop para o código Python nativo. Essa abordagem envolve o uso do protocolo iterador (ou do tipo PyBind11 py::iterable para o parâmetro de função) para processar cada elemento. Remover as transições repetidas entre Python e C++ é uma maneira eficaz de reduzir o tempo necessário para processar a sequência.
Solucionar erros de importação
Se receber uma ImportError mensagem quando tentar importar o módulo, pode resolvê-la de uma das seguintes formas:
Quando você cria através de uma referência de projeto, certifique-se de que as propriedades do seu projeto C++ correspondam ao ambiente Python ativado para seu projeto Python. Confirme se os mesmos locais de pasta estão em uso para os arquivos Include (.h) e Library (DLL).
Verifique se o arquivo de saída está nomeado corretamente, como superfastcode.pyd. Um nome ou extensão incorreto impede a importação do arquivo necessário.
Se você instalar seu módulo usando o arquivo setup.py , certifique-se de executar o
pipcomando no ambiente Python ativado para seu projeto Python. Quando você expande o ambiente Python ativo para seu projeto no Gerenciador de Soluções, você deve ver uma entrada para o projeto C++, como superfastcode.
Depurar código C++
O Visual Studio oferece suporte à depuração de código Python e C++ juntos. As etapas a seguir demonstram o processo de depuração para o projeto C++ superfastcode , mas o processo é o mesmo para o projeto superfastcode2 .
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto Python e selecione Propriedades.
No painel Propriedades , selecione a guia Depurar e, em seguida, selecione a opção Depurar>Habilitar depuração de código nativo .
Sugestão
Quando você ativa a depuração de código nativo, a janela de saída do Python pode fechar imediatamente após a conclusão do programa sem pausar e mostrando o prompt Pressione qualquer tecla para continuar . Para forçar a pausa e o prompt após ativar a depuração de código nativo, adicione o
-iargumento para o campo Executar>Argumentos do Interpretador na guia Depurar. Este argumento coloca o interpretador Python no modo interativo após a execução do código. O programa espera que você selecione Ctrl+Z+Enter para fechar a janela. Uma abordagem alternativa é adicionar instruçõesimport oseos.system("pause")no final do seu programa Python. Esse código duplica o prompt de pausa original.Selecione Salvar arquivo> (ou Ctrl+) para salvar as alterações de propriedade.
Na barra de ferramentas do Visual Studio, defina a configuração Build como Debug.
Como o código geralmente leva mais tempo para ser executado no depurador, talvez você queira alterar a
COUNTvariável em seu projeto Python .py arquivo para um valor que é cerca de cinco vezes menor do que o valor padrão. Por exemplo, altere-o de 500000 para 100000.No código C++, defina um ponto de interrupção na primeira linha do
tanh_implmétodo.Inicie o depurador selecionando Depurar>Iniciar Depuração ou use o atalho de teclado F5.
O depurador para quando o código do ponto de interrupção é executado. Se o ponto de interrupção não for atingido, verifique se a configuração está definida como Depurar e se você salvou o projeto, o que não acontece automaticamente quando você inicia o depurador.
No ponto de interrupção, você pode percorrer o código C++, examinar variáveis e assim por diante. Para obter mais informações sobre esses recursos, consulte Depurar Python e C++ juntos.
Abordagens alternativas
Você pode criar extensões Python de várias maneiras, conforme descrito na tabela a seguir. As duas primeiras linhas CPython e PyBind11, são discutidas neste artigo.
| Abordagem | Vintage | Utilizadores representativos |
|---|---|---|
Módulos de extensão C/C++ para CPython |
1991 | Biblioteca Standard |
| PyBind11 (recomendado para C++) | 2015 | |
| Cython (recomendado para C) | 2007 | Gevent, Kivy |
| HPy | 2019 | |
| mypyc | 2017 | |
| tipos | 2003 | OSPrip |
| CFFI | 2013 | Criptografia, Pypy |
| SWIG | 1996 | CRFSUITE |
| Boost.Python | 2002 | |
| cppyy | 2017 |