【问题标题】:Python: get string representation of PyObject?Python:获取 PyObject 的字符串表示?
【发布时间】:2011-07-18 10:12:30
【问题描述】:

我有一个 C python 扩展,我想打印一些诊断信息。

我收到一个字符串作为 PyObject*。

获取此对象的字符串表示形式的规范方法是什么,使其可用作 const char *?

更新:澄清强调访问为 const char *。

【问题讨论】:

    标签: python string pyobject


    【解决方案1】:

    使用PyObject_Repr(模仿Python的repr函数)或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);
    

    【讨论】:

    • 我正在为 Python 3 尝试 PyBytes_AsString(yourObject) 并且我收到 TypeError: expected bytes, str found
    • 我什至没有在我的回答中提到 PyBytes_AsString。您是否尝试过我在回答中的建议?
    • 我试过了,在 Py3.x 中,PyString 被 PyBytes 取代,但功能并不完全相同。我最终使用了:PyUnicode_AsUTF8(objectsRepresentation)
    • 别忘了Py_DECREF(objectsRepresentation),因为PyObject_Repr() 会返回一个新的参考!
    【解决方案2】:

    如果您使用的是 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);
    }
    

    【讨论】:

    • 如果我的PyObject 是纯python 字符串怎么办,如何将其转换为const char*
    • 请注意,PyObject_Repr 在您的字符串周围放置单引号。
    • @Montreal 与上面的示例相同,但省略 PyObject_Repr。为了安全起见,您可以使用if(!PyUnicode_CheckExact(obj)){...} 来验证PyObject *obj 确实是PyUnicode_Type
    • "~E~" 是什么意思?
    • @mkrieger1 在这个例子中,这将用字符串"~E~"替换无效字符/数据
    【解决方案3】:

    如果您只需要在 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);
    }
    

    【讨论】:

      【解决方案4】:

      尝试PyObject_Repr(模仿Python 的repr)或PyObject_Str(模仿Python 的str)。

      文档:

      计算一个字符串表示 对象o。返回字符串 表示成功,NULL 失败。这相当于 Python 表达式 repr(o)。调用者 repr() 内置函数。

      【讨论】:

      • 这看起来像我需要的......一旦我得到这些函数之一返回的 PyObject,我如何以 C 友好的方式访问它(例如调用 printf 等)
      【解决方案5】:

      PyObject *module_name; PyUnicode_AsUTF8(module_name)

      【讨论】:

        【解决方案6】:

        对于 python >=3.3:

        char* str = PyUnicode_1BYTE_DATA(py_object);
        

        是的,这是一个非常量指针,您可以通过它修改(不可变的)字符串。

        【讨论】:

          【解决方案7】:

          对于任意PyObject*,首先调用 PyObject_Repr()PyObject_Str() 获取 PyUnicode* 对象。

          在 Python 3.3 及更高版本中,调用 PyUnicode_AsUTF8AndSize。除了你想要 const char * 的 Python 字符串之外,此函数还需要一个可选地址来存储长度。

          Python 字符串是具有显式长度字段的对象,可能包含空字节,而 const char* 本身通常是指向以空字符结尾的 C 字符串的指针。将 Python 字符串转换为 C 字符串是一个潜在的有损操作。因此,所有其他可以从字符串返回 const char* 的 Python C-API 函数都是 deprecated

          如果您不关心如果字符串恰好包含嵌入的空字节而丢失一堆字符串,您可以将NULL 传递给size 参数。例如,

          PyObject* foo = PyUnicode_FromStringAndSize("foo\0bar", 7);
          
          printf("As const char*, ignoring length: %s\n",
              PyUnicode_AsUTF8AndSize(foo, NULL));
          

          打印

          As const char*, ignoring length: foo
          

          但您也可以传入size 变量的地址,以与const char* 一起使用,以确保您获得整个字符串。

          PyObject* foo = PyUnicode_FromStringAndSize("foo\0bar", 7);
          
          printf("Including size: ");
          size_t size;
          const char* data = PyUnicode_AsUTF8AndSize(foo, &size);
          fwrite(data, sizeof(data[0]), size, stdout);
          putchar('\n');
          

          在我的终端上,输出

          $ ./main | cat -v
          Including size: foo^@bar
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-03-08
            • 1970-01-01
            • 1970-01-01
            • 2010-11-03
            • 2012-11-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多