Introdução¶
A Interface de Programação de Aplicações (API) para Python fornece aos programadores C e C++ acesso ao interpretador Python em uma variedade de níveis. A API pode ser usada igualmente em C++, mas, para abreviar, geralmente é chamada de API Python/C. Existem dois motivos fundamentalmente diferentes para usar a API Python/C. A primeira razão é escrever módulos de extensão para propósitos específicos; esses são módulos C que estendem o interpretador Python. Este é provavelmente o uso mais comum. O segundo motivo é usar Python como um componente em uma aplicação maior; esta técnica é geralmente referida como incorporação Python em uma aplicação.
Escrever um módulo de extensão é um processo relativamente bem compreendido, no qual uma abordagem de “livro de receitas” funciona bem. Existem várias ferramentas que automatizam o processo até certo ponto. Embora as pessoas tenham incorporado o Python em outras aplicações desde sua existência inicial, o processo de incorporação do Python é menos direto do que escrever uma extensão.
Muitas funções da API são úteis independentemente de você estar incorporando ou estendendo o Python; além disso, a maioria das aplicações que incorporam Python também precisará fornecer uma extensão customizada, portanto, é provavelmente uma boa ideia se familiarizar com a escrita de uma extensão antes de tentar incorporar Python em uma aplicação real.
Padrões de codificação¶
Se você estiver escrevendo código C para inclusão no CPython, deve seguir as diretrizes e padrões definidos na PEP 7. Essas diretrizes se aplicam independentemente da versão do Python com a qual você está contribuindo. Seguir essas convenções não é necessário para seus próprios módulos de extensão de terceiros, a menos que você eventualmente espere contribuí-los para o Python.
Arquivos de inclusão¶
Todas as definições de função, tipo e macro necessárias para usar a API Python/C estão incluídas em seu código pela seguinte linha:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
Isso implica a inclusão dos seguintes cabeçalhos padrão: <stdio.h>
, <string.h>
, <errno.h>
, <limits.h>
, <assert.h>
e <stdlib.h>
(se disponível).
Nota
Uma vez que Python pode definir algumas definições de pré-processador que afetam os cabeçalhos padrão em alguns sistemas, você deve incluir Python.h
antes de quaisquer cabeçalhos padrão serem incluídos.
É recomendável sempre definir PY_SSIZE_T_CLEAN
antes de incluir Python.h
. Veja Análise de argumentos e construção de valores para uma descrição desta macro.
Todos os nomes visíveis ao usuário definidos por Python.h (exceto aqueles definidos pelos cabeçalhos padrão incluídos) têm um dos prefixos Py
ou _Py
. Nomes começando com _Py
são para uso interno pela implementação Python e não devem ser usados por escritores de extensão. Os nomes dos membros da estrutura não têm um prefixo reservado.
Nota
O código do usuário nunca deve definir nomes que começam com Py
ou _Py
. Isso confunde o leitor e coloca em risco a portabilidade do código do usuário para versões futuras do Python, que podem definir nomes adicionais começando com um desses prefixos.
Os arquivos de cabeçalho são normalmente instalados com Python. No Unix, eles estão localizados nos diretórios prefix/include/pythonversion/
e exec_prefix/include/pythonversion/
, onde prefix
e exec_prefix
são definidos pelos parâmetros correspondentes ao script configure e version do Python é '%d.%d' % sys.version_info[:2]
. No Windows, os cabeçalhos são instalados em prefix/include
, onde prefix
é o diretório de instalação especificado para o instalador.
Para incluir os cabeçalhos, coloque os dois diretórios (se diferentes) no caminho de pesquisa do compilador para as inclusões. Não coloque os diretórios pais no caminho de busca e então use #include <pythonX.Y/Python.h>
; isto irá quebrar em compilações multiplataforma, uma vez que os cabeçalhos independentes da plataforma em prefix
incluem os cabeçalhos específicos da plataforma de exec_prefix
.
Os usuários de C++ devem notar que embora a API seja definida inteiramente usando C, os arquivos de cabeçalho declaram apropriadamente os pontos de entrada como extern "C"
. Como resultado, não há necessidade de fazer nada especial para usar a API do C++.
Macros úteis¶
Diversas macros úteis são definidas nos arquivos de cabeçalho do Python. Muitas são definidas mais próximas de onde são úteis (por exemplo, Py_RETURN_NONE
). Outras de utilidade mais geral são definidas aqui. Esta não é necessariamente uma lista completa.
-
Py_UNREACHABLE
()¶ Use isso quando você tiver um caminho de código que não pode ser alcançado por design. Por exemplo, na cláusula
default:
em uma instruçãoswitch
para a qual todos os valores possíveis são incluídos nas instruçõescase
. Use isto em lugares onde você pode ficar tentado a colocar uma chamadaassert(0)
ouabort()
.No modo de lançamento, a macro ajuda o compilador a otimizar o código e evita um aviso sobre código inacessível. Por exemplo, a macro é implementada com
__builtin_unreachable()
no GCC em modo de lançamento.Um uso para
Py_UNREACHABLE()
é seguir uma chamada de uma função que nunca retorna, mas que não é declarada com_Py_NO_RETURN
.Se um caminho de código for um código muito improvável, mas puder ser alcançado em casos excepcionais, esta macro não deve ser usada. Por exemplo, sob condição de pouca memória ou se uma chamada de sistema retornar um valor fora do intervalo esperado. Nesse caso, é melhor relatar o erro ao chamador. Se o erro não puder ser reportado ao chamador,
Py_FatalError()
pode ser usada.Novo na versão 3.7.
-
Py_ABS
(x)¶ Retorna o valor absoluto de
x
.Novo na versão 3.3.
-
Py_MIN
(x, y)¶ Retorna o valor mínimo entre
x
ey
.Novo na versão 3.3.
-
Py_MAX
(x, y)¶ Retorna o valor máximo entre
x
ey
.Novo na versão 3.3.
-
Py_STRINGIFY
(x)¶ Converte
x
para uma string C. Por exemplo,Py_STRINGIFY(123)
retorna"123"
.Novo na versão 3.4.
-
Py_MEMBER_SIZE
(type, member)¶ Retorna o tamanho do
member
de uma estrutura (type
) em bytes.Novo na versão 3.6.
-
Py_CHARMASK
(c)¶ O argumento deve ser um caractere ou um número inteiro no intervalo [-128, 127] ou [0, 255]. Esta macro retorna
c
convertido em umunsigned char
.
-
Py_GETENV
(s)¶ Como
getenv(s)
, mas retornaNULL
se-E
foi passada na linha de comando (isto é, sePy_IgnoreEnvironmentFlag
estiver definida).
-
Py_UNUSED
(arg)¶ Use isso para argumentos não usados em uma definição de função para silenciar avisos do compilador. Exemplo:
int func(int a, int Py_UNUSED(b)) { return a; }
.Novo na versão 3.4.
-
Py_DEPRECATED
(version)¶ Use isso para declarações descontinuadas. A macro deve ser colocada antes do nome do símbolo.
Exemplo:
Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void);
Alterado na versão 3.8: Suporte a MSVC foi adicionado.
-
PyDoc_STRVAR
(name, str)¶ Cria uma variável com o nome
name
que pode ser usada em docstrings. Se o Python for compilado sem docstrings, o valor estará vazio.Use
PyDoc_STRVAR
para docstrings para ter suporte à compilação do Python sem docstrings, conforme especificado em PEP 7.Exemplo:
PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element."); static PyMethodDef deque_methods[] = { // ... {"pop", (PyCFunction)deque_pop, METH_NOARGS, pop_doc}, // ... }
-
PyDoc_STR
(str)¶ Cria uma docstring para a string de entrada fornecida ou uma string vazia se docstrings estiverem desabilitadas.
Use
PyDoc_STR
ao especificar docstrings para ter suporte à compilação do Python sem docstrings, conforme especificado em PEP 7.Exemplo:
static PyMethodDef pysqlite_row_methods[] = { {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, PyDoc_STR("Returns the keys of the row.")}, {NULL, NULL} };
Objetos, tipos e contagens de referências¶
A maioria das funções da API Python/C tem um ou mais argumentos, bem como um valor de retorno do tipo PyObject*
. Este tipo é um ponteiro para um tipo de dados opaco que representa um objeto Python arbitrário. Como todos os tipos de objeto Python são tratados da mesma maneira pela linguagem Python na maioria das situações (por exemplo, atribuições, regras de escopo e passagem de argumento), é adequado que eles sejam representados por um único tipo C. Quase todos os objetos Python vivem na pilha: você nunca declara uma variável automática ou estática do tipo PyObject
, variáveis de apenas ponteiro do tipo PyObject*
podem ser declaradas. A única exceção são os objetos de tipo; uma vez que estes nunca devem ser desalocados, eles são normalmente objetos estáticos PyTypeObject
.
Todos os objetos Python (mesmo inteiros Python) têm um tipo e uma contagem de referências. O tipo de um objeto determina que tipo de objeto ele é (por exemplo, um número inteiro, uma lista ou uma função definida pelo usuário; existem muitos mais, conforme explicado em A hierarquia de tipos padrão). Para cada um dos tipos conhecidos, há uma macro para verificar se um objeto é desse tipo; por exemplo, PyList_Check(a)
é verdadeiro se (e somente se) o objeto apontado por a for uma lista Python.
Contagens de referências¶
The reference count is important because today’s computers have a finite (and often severely limited) memory size; it counts how many different places there are that have a strong reference to an object. Such a place could be another object, or a global (or static) C variable, or a local variable in some C function. When the last strong reference to an object is released (i.e. its reference count becomes zero), the object is deallocated. If it contains references to other objects, those references are released. Those other objects may be deallocated in turn, if there are no more references to them, and so on. (There’s an obvious problem with objects that reference each other here; for now, the solution is “don’t do that.”)
Reference counts are always manipulated explicitly. The normal way is
to use the macro Py_INCREF()
to take a new reference to an
object (i.e. increment its reference count by one),
and Py_DECREF()
to release that reference (i.e. decrement the
reference count by one). The Py_DECREF()
macro
is considerably more complex than the incref one, since it must check whether
the reference count becomes zero and then cause the object’s deallocator to be
called. The deallocator is a function pointer contained in the object’s type
structure. The type-specific deallocator takes care of releasing references
for other objects contained in the object if this is a compound
object type, such as a list, as well as performing any additional finalization
that’s needed. There’s no chance that the reference count can overflow; at
least as many bits are used to hold the reference count as there are distinct
memory locations in virtual memory (assuming sizeof(Py_ssize_t) >= sizeof(void*)
).
Thus, the reference count increment is a simple operation.
It is not necessary to hold a strong reference (i.e. increment the reference count) for every local variable that contains a pointer to an object. In theory, the object’s reference count goes up by one when the variable is made to point to it and it goes down by one when the variable goes out of scope. However, these two cancel each other out, so at the end the reference count hasn’t changed. The only real reason to use the reference count is to prevent the object from being deallocated as long as our variable is pointing to it. If we know that there is at least one other reference to the object that lives at least as long as our variable, there is no need to take a new strong reference (i.e. increment the reference count) temporarily. An important situation where this arises is in objects that are passed as arguments to C functions in an extension module that are called from Python; the call mechanism guarantees to hold a reference to every argument for the duration of the call.
However, a common pitfall is to extract an object from a list and hold on to it
for a while without taking a new reference. Some other operation might
conceivably remove the object from the list, releasing that reference,
and possibly deallocating it. The real danger is that innocent-looking
operations may invoke arbitrary Python code which could do this; there is a code
path which allows control to flow back to the user from a Py_DECREF()
, so
almost any operation is potentially dangerous.
A safe approach is to always use the generic operations (functions whose name
begins with PyObject_
, PyNumber_
, PySequence_
or PyMapping_
).
These operations always create a new strong reference
(i.e. increment the reference count) of the object they return.
This leaves the caller with the responsibility to call Py_DECREF()
when
they are done with the result; this soon becomes second nature.
Detalhes da contagem de referências¶
The reference count behavior of functions in the Python/C API is best explained
in terms of ownership of references. Ownership pertains to references, never
to objects (objects are not owned: they are always shared). “Owning a
reference” means being responsible for calling Py_DECREF on it when the
reference is no longer needed. Ownership can also be transferred, meaning that
the code that receives ownership of the reference then becomes responsible for
eventually releasing it by calling Py_DECREF()
or Py_XDECREF()
when it’s no longer needed—or passing on this responsibility (usually to its
caller). When a function passes ownership of a reference on to its caller, the
caller is said to receive a new reference. When no ownership is transferred,
the caller is said to borrow the reference. Nothing needs to be done for a
borrowed reference.
Por outro lado, quando uma função de chamada passa uma referência a um objeto, há duas possibilidades: a função rouba uma referência ao objeto, ou não. Roubar uma referência significa que quando você passa uma referência para uma função, essa função presume que agora ela possui essa referência e você não é mais responsável por ela.
Poucas funções roubam referências; as duas exceções notáveis são PyList_SetItem()
e PyTuple_SetItem()
, que roubam uma referência para o item (mas não para a tupla ou lista na qual o item é colocado!). Essas funções foram projetadas para roubar uma referência devido a um idioma comum para preencher uma tupla ou lista com objetos recém-criados; por exemplo, o código para criar a tupla (1, 2, "three")
pode ser parecido com isto (esquecendo o tratamento de erros por enquanto; uma maneira melhor de codificar isso é mostrada abaixo):
PyObject *t;
t = PyTuple_New(3);
PyTuple_SetItem(t, 0, PyLong_FromLong(1L));
PyTuple_SetItem(t, 1, PyLong_FromLong(2L));
PyTuple_SetItem(t, 2, PyUnicode_FromString("three"));
Aqui, PyLong_FromLong()
retorna uma nova referência que é imediatamente roubada por PyTuple_SetItem()
. Quando você quiser continuar usando um objeto, embora a referência a ele seja roubada, use Py_INCREF()
para obter outra referência antes de chamar a função de roubo de referência.
A propósito, PyTuple_SetItem()
é a única maneira de definir itens de tupla; PySequence_SetItem()
e PyObject_SetItem()
se recusam a fazer isso, pois tuplas são um tipo de dados imutável. Você só deve usar PyTuple_SetItem()
para tuplas que você mesmo está criando.
O código equivalente para preencher uma lista pode ser escrita usando PyList_New()
e PyList_SetItem()
.
No entanto, na prática, você raramente usará essas maneiras de criar e preencher uma tupla ou lista. Existe uma função genérica, Py_BuildValue()
, que pode criar objetos mais comuns a partir de valores C, dirigidos por uma string de formato. Por exemplo, os dois blocos de código acima podem ser substituídos pelos seguintes (que também cuidam da verificação de erros):
PyObject *tuple, *list;
tuple = Py_BuildValue("(iis)", 1, 2, "three");
list = Py_BuildValue("[iis]", 1, 2, "three");
It is much more common to use PyObject_SetItem()
and friends with items
whose references you are only borrowing, like arguments that were passed in to
the function you are writing. In that case, their behaviour regarding references
is much saner, since you don’t have to take a new reference just so you
can give that reference away (“have it be stolen”). For example, this function
sets all items of a list (actually, any mutable sequence) to a given item:
int
set_all(PyObject *target, PyObject *item)
{
Py_ssize_t i, n;
n = PyObject_Length(target);
if (n < 0)
return -1;
for (i = 0; i < n; i++) {
PyObject *index = PyLong_FromSsize_t(i);
if (!index)
return -1;
if (PyObject_SetItem(target, index, item) < 0) {
Py_DECREF(index);
return -1;
}
Py_DECREF(index);
}
return 0;
}
A situação é ligeiramente diferente para os valores de retorno da função. Embora passar uma referência para a maioria das funções não altere suas responsabilidades de propriedade para aquela referência, muitas funções que retornam uma referência a um objeto fornecem a propriedade da referência. O motivo é simples: em muitos casos, o objeto retornado é criado instantaneamente e a referência que você obtém é a única referência ao objeto. Portanto, as funções genéricas que retornam referências a objetos, como PyObject_GetItem()
e PySequence_GetItem()
, sempre retornam uma nova referência (o chamador torna-se o dono da referência).
É importante perceber que se você possui uma referência retornada por uma função depende de qual função você chama apenas — a plumagem (o tipo do objeto passado como um argumento para a função) não entra nela! Assim, se você extrair um item de uma lista usando PyList_GetItem()
, você não possui a referência — mas se obtiver o mesmo item da mesma lista usando PySequence_GetItem()
(que leva exatamente os mesmos argumentos), você possui uma referência ao objeto retornado.
Aqui está um exemplo de como você poderia escrever uma função que calcula a soma dos itens em uma lista de inteiros; uma vez usando PyList_GetItem()
, e uma vez usando PySequence_GetItem()
.
long
sum_list(PyObject *list)
{
Py_ssize_t i, n;
long total = 0, value;
PyObject *item;
n = PyList_Size(list);
if (n < 0)
return -1; /* Not a list */
for (i = 0; i < n; i++) {
item = PyList_GetItem(list, i); /* Can't fail */
if (!PyLong_Check(item)) continue; /* Skip non-integers */
value = PyLong_AsLong(item);
if (value == -1 && PyErr_Occurred())
/* Integer too big to fit in a C long, bail out */
return -1;
total += value;
}
return total;
}
long
sum_sequence(PyObject *sequence)
{
Py_ssize_t i, n;
long total = 0, value;
PyObject *item;
n = PySequence_Length(sequence);
if (n < 0)
return -1; /* Has no length */
for (i = 0; i < n; i++) {
item = PySequence_GetItem(sequence, i);
if (item == NULL)
return -1; /* Not a sequence, or other failure */
if (PyLong_Check(item)) {
value = PyLong_AsLong(item);
Py_DECREF(item);
if (value == -1 && PyErr_Occurred())
/* Integer too big to fit in a C long, bail out */
return -1;
total += value;
}
else {
Py_DECREF(item); /* Discard reference ownership */
}
}
return total;
}
Tipos¶
Existem alguns outros tipos de dados que desempenham um papel significativo na API Python/C; a maioria são tipos C simples, como int
, long
, double
e char*
. Alguns tipos de estrutura são usados para descrever tabelas estáticas usadas para listar as funções exportadas por um módulo ou os atributos de dados de um novo tipo de objeto, e outro é usado para descrever o valor de um número complexo. Eles serão discutidos junto com as funções que os utilizam.
-
type
Py_ssize_t
¶ - Part of the Stable ABI.
Um tipo integral assinado tal que
sizeof(Py_ssize_t) == sizeof(size_t)
. C99 não define tal coisa diretamente (size_t é um tipo integral não assinado). Veja PEP 353 para mais detalhes.PY_SSIZE_T_MAX
é o maior valor positivo do tipoPy_ssize_t
.
Exceções¶
O programador Python só precisa lidar com exceções se o tratamento de erros específico for necessário; as exceções não tratadas são propagadas automaticamente para o chamador, depois para o chamador e assim por diante, até chegarem ao interpretador de nível superior, onde são relatadas ao usuário acompanhadas por um traceback (situação da pilha de execução).
Para programadores C, entretanto, a verificação de erros sempre deve ser explícita. Todas as funções na API Python/C podem levantar exceções, a menos que uma declaração explícita seja feita de outra forma na documentação de uma função. Em geral, quando uma função encontra um erro, ela define uma exceção, descarta todas as referências de objeto de sua propriedade e retorna um indicador de erro. Se não for documentado de outra forma, este indicador é NULL
ou -1
, dependendo do tipo de retorno da função. Algumas funções retornam um resultado booleano verdadeiro/falso, com falso indicando um erro. Muito poucas funções não retornam nenhum indicador de erro explícito ou têm um valor de retorno ambíguo e requerem teste explícito para erros com PyErr_Occurred()
. Essas exceções são sempre documentadas explicitamente.
O estado de exceção é mantido no armazenamento por thread (isso é equivalente a usar o armazenamento global em uma aplicação sem thread). Uma thread pode estar em um de dois estados: ocorreu uma exceção ou não. A função PyErr_Occurred()
pode ser usada para verificar isso: ela retorna uma referência emprestada ao objeto do tipo de exceção quando uma exceção ocorreu, e NULL
caso contrário. Existem várias funções para definir o estado de exceção: PyErr_SetString()
é a função mais comum (embora não a mais geral) para definir o estado de exceção, e PyErr_Clear()
limpa o estado da exceção.
O estado de exceção completo consiste em três objetos (todos os quais podem ser NULL
): o tipo de exceção, o valor de exceção correspondente e o traceback. Eles têm os mesmos significados que o resultado do Python de sys.exc_info()
; no entanto, eles não são os mesmos: os objetos Python representam a última exceção sendo tratada por uma instrução Python try
… except
, enquanto o estado de exceção de nível C só existe enquanto uma exceção está sendo transmitido entre funções C até atingir o loop principal do interpretador de bytecode Python, que se encarrega de transferi-lo para sys.exc_info()
e amigos.
Observe que a partir do Python 1.5, a maneira preferida e segura para thread para acessar o estado de exceção do código Python é chamar a função sys.exc_info()
, que retorna o estado de exceção por thread para o código Python. Além disso, a semântica de ambas as maneiras de acessar o estado de exceção mudou, de modo que uma função que captura uma exceção salvará e restaurará o estado de exceção de seu segmento de modo a preservar o estado de exceção de seu chamador. Isso evita bugs comuns no código de tratamento de exceções causados por uma função aparentemente inocente sobrescrevendo a exceção sendo tratada; também reduz a extensão da vida útil frequentemente indesejada para objetos que são referenciados pelos quadros de pilha no traceback.
Como princípio geral, uma função que chama outra função para realizar alguma tarefa deve verificar se a função chamada levantou uma exceção e, em caso afirmativo, passar o estado da exceção para seu chamador. Ele deve descartar todas as referências de objeto que possui e retornar um indicador de erro, mas não deve definir outra exceção — que sobrescreveria a exceção que acabou de ser gerada e perderia informações importantes sobre a causa exata do erro.
Um exemplo simples de detecção de exceções e transmiti-las é mostrado no exemplo sum_sequence()
acima. Acontece que este exemplo não precisa limpar nenhuma referência de propriedade quando detecta um erro. A função de exemplo a seguir mostra alguma limpeza de erro. Primeiro, para lembrar por que você gosta de Python, mostramos o código Python equivalente:
def incr_item(dict, key):
try:
item = dict[key]
except KeyError:
item = 0
dict[key] = item + 1
Aqui está o código C correspondente, em toda sua glória:
int
incr_item(PyObject *dict, PyObject *key)
{
/* Objects all initialized to NULL for Py_XDECREF */
PyObject *item = NULL, *const_one = NULL, *incremented_item = NULL;
int rv = -1; /* Return value initialized to -1 (failure) */
item = PyObject_GetItem(dict, key);
if (item == NULL) {
/* Handle KeyError only: */
if (!PyErr_ExceptionMatches(PyExc_KeyError))
goto error;
/* Clear the error and use zero: */
PyErr_Clear();
item = PyLong_FromLong(0L);
if (item == NULL)
goto error;
}
const_one = PyLong_FromLong(1L);
if (const_one == NULL)
goto error;
incremented_item = PyNumber_Add(item, const_one);
if (incremented_item == NULL)
goto error;
if (PyObject_SetItem(dict, key, incremented_item) < 0)
goto error;
rv = 0; /* Success */
/* Continue with cleanup code */
error:
/* Cleanup code, shared by success and failure path */
/* Use Py_XDECREF() to ignore NULL references */
Py_XDECREF(item);
Py_XDECREF(const_one);
Py_XDECREF(incremented_item);
return rv; /* -1 for error, 0 for success */
}
Este exemplo representa um uso endossado da instrução goto
em C! Ele ilustra o uso de PyErr_ExceptionMatches()
e PyErr_Clear()
para lidar com exceções específicas, e o uso de Py_XDECREF()
para descartar referências de propriedade que podem ser NULL
(observe o 'X'
no nome; Py_DECREF()
travaria quando confrontado com uma referência NULL
). É importante que as variáveis usadas para manter as referências de propriedade sejam inicializadas com NULL
para que isso funcione; da mesma forma, o valor de retorno proposto é inicializado para -1
(falha) e apenas definido para sucesso após a chamada final feita ser bem sucedida.
Incorporando Python¶
A única tarefa importante com a qual apenas os incorporadores (em oposição aos escritores de extensão) do interpretador Python precisam se preocupar é a inicialização e, possivelmente, a finalização do interpretador Python. A maior parte da funcionalidade do interpretador só pode ser usada após a inicialização do interpretador.
A função de inicialização básica é Py_Initialize()
. Isso inicializa a tabela de módulos carregados e cria os módulos fundamentais builtins
, __main__
e sys
. Ela também inicializa o caminho de pesquisa de módulos (sys.path
).
Py_Initialize()
não define a “lista de argumentos de script” (sys.argv
). Se esta variável for necessária para o código Python que será executado posteriormente, ela deve ser definida explicitamente com uma chamada com PySys_SetArgvEx(argc, argv, updatepath)
após a chamada de Py_Initialize()
.
Na maioria dos sistemas (em particular, no Unix e no Windows, embora os detalhes sejam ligeiramente diferentes), Py_Initialize()
calcula o caminho de pesquisa de módulos com base em sua melhor estimativa para a localização do executável do interpretador Python padrão, presumindo que a biblioteca Python é encontrada em um local fixo em relação ao executável do interpretador Python. Em particular, ele procura por um diretório chamado lib/pythonX.Y
relativo ao diretório pai onde o executável chamado python
é encontrado no caminho de pesquisa de comandos do shell (a variável de ambiente PATH
).
Por exemplo, se o executável Python for encontrado em /usr/local/bin/python
, ele presumirá que as bibliotecas estão em /usr/local/lib/pythonX.Y
. (Na verdade, este caminho particular também é o local reserva, usado quando nenhum arquivo executável chamado python
é encontrado ao longo de PATH
.) O usuário pode substituir este comportamento definindo a variável de ambiente PYTHONHOME
, ou insira diretórios adicionais na frente do caminho padrão definindo PYTHONPATH
.
A aplicação de incorporação pode orientar a pesquisa chamando Py_SetProgramName(file)
antes de chamar Py_Initialize()
. Observe que PYTHONHOME
ainda substitui isso e PYTHONPATH
ainda é inserido na frente do caminho padrão. Uma aplicação que requer controle total deve fornecer sua própria implementação de Py_GetPath()
, Py_GetPrefix()
, Py_GetExecPrefix()
e Py_GetProgramFullPath()
(todas definidas em Modules/getpath.c
).
Às vezes, é desejável “desinicializar” o Python. Por exemplo, a aplicação pode querer iniciar novamente (fazer outra chamada para Py_Initialize()
) ou a aplicação simplesmente termina com o uso de Python e deseja liberar memória alocada pelo Python. Isso pode ser feito chamando Py_FinalizeEx()
. A função Py_IsInitialized()
retorna verdadeiro se o Python está atualmente no estado inicializado. Mais informações sobre essas funções são fornecidas em um capítulo posterior. Observe que Py_FinalizeEx()
não libera toda a memória alocada pelo interpretador Python, por exemplo, a memória alocada por módulos de extensão atualmente não pode ser liberada.
Compilações de depuração¶
Python pode ser compilado com várias macros para permitir verificações extras do interpretador e módulos de extensão. Essas verificações tendem a adicionar uma grande quantidade de sobrecarga ao tempo de execução, portanto, não são habilitadas por padrão.
Uma lista completa dos vários tipos de compilações de depuração está no arquivo Misc/SpecialBuilds.txt
na distribuição do código-fonte do Python. Estão disponíveis compilações que oferecem suporte ao rastreamento de contagens de referências, depuração do alocador de memória ou criação de perfil de baixo nível do laço do interpretador principal. Apenas as compilações usadas com mais frequência serão descritas no restante desta seção.
Compilar o interpretador com a macro Py_DEBUG
definida produz o que geralmente se entende por uma compilação de depuração do Python. Py_DEBUG
é habilitada na compilação Unix adicionando --with-pydebug
ao comando ./configure
. Também está implícito na presença da macro não específica do Python _DEBUG
. Quando Py_DEBUG
está habilitado na compilação do Unix, a otimização do compilador é desabilitada.
Além da depuração de contagem de referências descrita abaixo, verificações extras são realizadas, consulte Compilação de Depuração do Python.
Definir Py_TRACE_REFS
habilita o rastreamento de referência (veja a opção opção --with-trace-refs de configure
). Quando definida, uma lista circular duplamente vinculada de objetos ativos é mantida adicionando dois campos extras a cada PyObject
. As alocações totais também são rastreadas. Ao sair, todas as referências existentes são impressas. (No modo interativo, isso acontece após cada instrução executada pelo interpretador.)
Consulte Misc/SpecialBuilds.txt
na distribuição do código-fonte Python para informações mais detalhadas.