Python: получить строковое представление PyObject?

У меня есть расширение C Python, и я хотел бы распечатать некоторые диагностические данные.

Я получаю строку как PyObject*.

Каков канонический способ получить строковое представление этого объекта, чтобы его можно было использовать как const char *?

обновление: разъяснено, чтобы выделить доступ как const char *.


person Mark Harrison    schedule 18.03.2011    source источник


Ответы (6)


Используйте PyObject_Repr (для имитации функции repr Python) или PyObject_Str (для имитации str), а затем вызовите PyString_AsString, чтобы получить char * (вы можете и обычно должны использовать его как const char*, например:

PyObject* objectsRepresentation = PyObject_Repr(yourObject);
const char* s = PyString_AsString(objectsRepresentation);

Этот метод подходит для любого PyObject. Если вы абсолютно уверены, что yourObject — это строка Python, а не что-то еще, например, число, вы можете пропустить первую строку и просто сделать:

const char* s = PyString_AsString(yourObject);
person piokuc    schedule 21.11.2011
comment
Я пытаюсь PyBytes_AsString(yourObject) для Python 3, и я получаю TypeError: ожидаемые байты, найденная строка - person brita_; 06.02.2015
comment
Я даже не упомянул PyBytes_AsString в своем ответе. Вы пробовали то, что я предложил в своем ответе? - person piokuc; 09.02.2015
comment
Я пробовал, в Py3.x PyString заменили на PyBytes, но с не совсем той же функциональностью. В итоге я использовал: PyUnicode_AsUTF8 (objectsRepresentation) - person brita_; 10.02.2015
comment
Не забудьте Py_DECREF(objectsRepresentation), так как PyObject_Repr() возвращает новую ссылку! - person Steve; 20.02.2016

Вот правильный ответ, если вы используете Python 3:

static void reprint(PyObject *obj) {
    PyObject* repr = PyObject_Repr(obj);
    PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~");
    const char *bytes = PyBytes_AS_STRING(str);

    printf("REPR: %s\n", bytes);

    Py_XDECREF(repr);
    Py_XDECREF(str);
}
person Romuald Brunet    schedule 13.09.2017
comment
И что, если мой PyObject представляет собой обычную строку Python, как я могу преобразовать ее в const char*? - person Montreal; 07.06.2018
comment
Обратите внимание, что PyObject_Repr заключает вашу строку в одинарные кавычки. - person IDDQD; 14.01.2019
comment
@Montreal То же, что и в примере выше, но без PyObject_Repr. В целях безопасности вы можете использовать if(!PyUnicode_CheckExact(obj)){...}, чтобы убедиться, что PyObject *obj действительно является PyUnicode_Type. - person IDDQD; 14.01.2019
comment
Что означает "~E~"? - person mkrieger1; 12.06.2019
comment
@mkrieger1 в этом примере заменит недопустимые символы/данные строкой "~E~" - person Romuald Brunet; 13.06.2019

Если вам нужно просто распечатать объект в Python 3, вы можете использовать одну из этих функций:

static void print_str(PyObject *o)
{
    PyObject_Print(o, stdout, Py_PRINT_RAW);
}

static void print_repr(PyObject *o)
{
    PyObject_Print(o, stdout, 0);
}
person Maxim Khrisanfov    schedule 05.08.2018

Попробуйте PyObject_Repr (чтобы имитировать repr Python) или PyObject_Str (чтобы имитировать str Python).

Документы:

Вычислите строковое представление объекта o. Возвращает строковое представление в случае успеха, NULL в случае неудачи. Это эквивалент выражения Python repr(o). Вызывается встроенной функцией repr().

person Alexander Gessler    schedule 18.03.2011
comment
это похоже на то, что мне нужно... После того, как я получил PyObject, возвращенный одной из этих функций, как мне получить к нему доступ C-дружественным способом (например, для вызова printf и т. д.) - person Mark Harrison; 18.03.2011

PyObject *имя_модуля; PyUnicode_AsUTF8 (имя_модуля)

person Pulller    schedule 09.04.2020

Для питона ›=3.3:

char* str = PyUnicode_1BYTE_DATA(py_object);

Да, это неконстантный указатель, вы потенциально можете изменить (неизменяемую) строку через него.

person Mikhail    schedule 15.01.2021