如何处理字符串以在 Python 3 中正确嵌入

Posted

技术标签:

【中文标题】如何处理字符串以在 Python 3 中正确嵌入【英文标题】:How to handle string for embedding properly in Python 3 【发布时间】:2018-03-08 07:55:08 【问题描述】:

我正在尝试将 python embedding 与 Python 3 一起使用,但不幸的是,使用它时会出现一些奇怪的结果。以下是源代码:

场景 1

/tmp/main.cpp

#include <python3.6/Python.h>
//#include <python2.7/Python.h>
using namespace std;

int main()

    Py_Initialize();
    PyObject* sysPath = PySys_GetObject("path");
    PyObject *path = PyBytes_FromString("/tmp");
    int result = PyList_Append(sysPath, path);
    PyRun_SimpleString("from hello import hello\n"); // there is a /tmp/hello.py
    Py_Finalize();
    return 0;

如果我像这样在 Python 2.7 中编译和运行上述代码,它没有显示任何错误:

g++ -L/usr/lib/python2.7/config-x86_64-linux-gnu/ -g -o main main.cpp -I/usr/include/python2.7 -lpython2.7

但是,如果我像这样在 Python 3.6 中编译和运行代码:

g++ -L/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu/ -g -o main main.cpp -I/usr/include/ -lpython3.6

它会显示以下错误:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/__init__.py", line 142, in <module>
    from . import add_newdocs
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/add_newdocs.py", line 13, in <module>
    from numpy.lib import add_newdoc
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/lib/__init__.py", line 8, in <module>
    from .type_check import *
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/lib/type_check.py", line 11, in <module>
    import numpy.core.numeric as _nx
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/core/__init__.py", line 35, in <module>
    from . import _internal  # for freeze programs
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/core/_internal.py", line 12, in <module>
    from numpy.compat import basestring
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/compat/__init__.py", line 14, in <module>
    from . import py3k
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/compat/py3k.py", line 14, in <module>
    from pathlib import Path
  File "/usr/lib/python3.6/pathlib.py", line 4, in <module>
    import ntpath
  File "/usr/lib/python3.6/ntpath.py", line 278, in <module>
    from nt import _getvolumepathname
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 951, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 894, in _find_spec
  File "<frozen importlib._bootstrap_external>", line 1157, in find_spec
  File "<frozen importlib._bootstrap_external>", line 1129, in _get_spec
  File "<frozen importlib._bootstrap_external>", line 1268, in find_spec
  File "<frozen importlib._bootstrap_external>", line 60, in _path_join
  File "<frozen importlib._bootstrap_external>", line 60, in <listcomp>
TypeError: a bytes-like object is required, not 'str'
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 57, in apport_excepthook
    from cStringIO import StringIO
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 951, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 894, in _find_spec
  File "<frozen importlib._bootstrap_external>", line 1157, in find_spec
  File "<frozen importlib._bootstrap_external>", line 1129, in _get_spec
  File "<frozen importlib._bootstrap_external>", line 1268, in find_spec
  File "<frozen importlib._bootstrap_external>", line 60, in _path_join
  File "<frozen importlib._bootstrap_external>", line 60, in <listcomp>
TypeError: a bytes-like object is required, not 'str'

Original exception was:
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/__init__.py", line 142, in <module>
    from . import add_newdocs
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/add_newdocs.py", line 13, in <module>
    from numpy.lib import add_newdoc
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/lib/__init__.py", line 8, in <module>
    from .type_check import *
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/lib/type_check.py", line 11, in <module>
    import numpy.core.numeric as _nx
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/core/__init__.py", line 35, in <module>
    from . import _internal  # for freeze programs
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/core/_internal.py", line 12, in <module>
    from numpy.compat import basestring
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/compat/__init__.py", line 14, in <module>
    from . import py3k
  File "/home/tfidm/.local/lib/python3.6/site-packages/numpy/compat/py3k.py", line 14, in <module>
    from pathlib import Path
  File "/usr/lib/python3.6/pathlib.py", line 4, in <module>
    import ntpath
  File "/usr/lib/python3.6/ntpath.py", line 278, in <module>
    from nt import _getvolumepathname
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 951, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 894, in _find_spec
  File "<frozen importlib._bootstrap_external>", line 1157, in find_spec
  File "<frozen importlib._bootstrap_external>", line 1129, in _get_spec
  File "<frozen importlib._bootstrap_external>", line 1268, in find_spec
  File "<frozen importlib._bootstrap_external>", line 60, in _path_join
  File "<frozen importlib._bootstrap_external>", line 60, in <listcomp>
TypeError: a bytes-like object is required, not 'str'

场景 2

如果我删除三行以将当前目录附加到系统路径,如下所示:

Py_Initialize();
PyRun_SimpleString("from hello import hello\n");

在 Python 2 和 Python 3 中都会显示以下错误:

ModuleNotFoundError: No module named 'hello'

从场景 2 中,我们可以观察到将当前目录添加到系统路径的行是必需的。添加路径完成后,场景 1 中的代码仅适用于 Python 2。 Python 3 的错误日志显示它需要像字节对象而不是字符串这样的东西。但是我不知道如何将嵌入与字节对象一起使用,因为我在官方 python 网站或网络上的任何其他地方都找不到它。

请有人解释一下如何在 Python 3 中正确使用嵌入?

【问题讨论】:

【参考方案1】:

Python 3 sys.path 采用 Unicode 字符串,而不是字节字符串。不要使用PyBytes_FromString 创建路径元素。

请改用PyUnicode_FromString,至少在嵌入 Python 3 时是这样。

如果路径元素仅包含 ASCII 字符,您可以在 Python 2 中使用相同的函数。Python 2.x 中 sys.path 元素中的非 ASCII 字符支持参差不齐,并且取决于操作系统。

【讨论】:

以上是关于如何处理字符串以在 Python 3 中正确嵌入的主要内容,如果未能解决你的问题,请参考以下文章

您打算如何处理向 Python 3 的迁移?

如何处理我的 JavaScript 作业? [关闭]

您将如何处理字符串通配符,而不仅仅是比较正确的值?

c#字符串中拼接参数该如何处理?

嵌入 UINavigationController 时如何处理 UIView 区域减少的问题

Python反射机制中参数问题如何处理?