【问题标题】:Python with non-latin-1 PYTHONHOME path具有非 latin-1 PYTHONHOME 路径的 Python
【发布时间】:2016-09-15 21:46:43
【问题描述】:

在我的例子中,我将 Python 嵌入到我的应用程序中。当我的应用程序路径包含非 latin-1 字符时,Py_Initialize 在内部调用 exit(1)(稍后会提供更多信息)。

所以我检查了是否可以使用标准解释器可执行文件重现此内容。

当 PYTHONHOME 的路径包含 latin-1 字符集之外的字符时,Windows 上的 Python-2.7.x 似乎不起作用。问题是模块 site 无法找到并导入。由于变音符号似乎有效,这里的实际限制是什么?仅支持 latin-1 吗?那为什么它可以在 OSX 上运行呢?

C:\Users\ъ\Python27\python.exe    // fails to start (KOI8-R)
         ^
C:\Users\ġ\Python27\python.exe    // fails to start (latin-3)
         ^
C:\Users\ä\Python27\python.exe    // works fine (latin-1)
         ^

有什么想法吗?

背景:

我还没有逐步完成代码,但是当 site 不可用时,Python 2.6 和 Python 2.7 的行为也会有所不同。 Py 2.6 只是打印一条消息,Py 2.7 拒绝启动。

static void
initsite(void)
{
    PyObject *m;
    m = PyImport_ImportModule("site");
    if (m == NULL) {
        ...

        // Python 2.7 and later
        exit(1);

        // Python 2.6 and prior
        PyFile_WriteString("'import site' failed; traceback:\n", f);
    }
    ...
}

Python 2.7https://github.com/enthought/Python-2.7.3/blob/master/Python/pythonrun.c#L725

Python 2.6https://github.com/python-git/python/blob/master/Python/pythonrun.c#L705

【问题讨论】:

  • 你试过用 Python 3 代替吗?他们重做了 Unicode 处理,而且更干净。我的建议实际上是尽可能使用 3,仅在必要时使用 2。
  • 在 Python 3 中它(应该)工作/秒,是的。我必须坚持使用 Python 2,因为这是我们嵌入到我们软件中的版本,不过将来会发生变化。
  • 您能详细说明您是如何在您的应用程序中“嵌入”Python 的吗?从 C/C++ 调用它?你使用的机制是什么?你设置了 PYTHONHOME 吗?如果是这样,你如何设置它?作为旁注,OS FS wrt 到 unicode 路径的行为在 Windows、Mac 和 Linux/POSIX 上变化很大。在 CPython 2 中处理这个问题的方法有时需要一些摆弄......虽然我确实成功地与它搏斗了几次
  • 使用 C API 中的 Py_Initialize, ...。我尝试了 PYTHOMHOME 和相应的 C 函数(Py_SetPathPy_SetPythonhome、...),但没有成功。顺便说一句,如果安装在给定的路径上,Python 2.7(没有嵌入)也不起作用。
  • MS Windows 与 OS X 的不同之处在于那里的基本字符集是 UTF-16。对于后向代码,它还提供了一个“ANSI”API,它使用单字节字符串,但不能表示整个 Unicode 范围。我很确定 Python 2 永远不会升级到使用完全支持 Unicode 的 win32 API,所以任何麻烦都是徒劳的,除非你至少升级到 Python 3。

标签: python windows utf-8 latin1


【解决方案1】:

我认为问题在于,在内部,Python2 将平台系统编码中的所有内容都处理为字节字符串,该平台系统编码(在西欧)CP1252 是 Latin-1 的变体。因此,它无法正确处理包含其他字符的 PYTHONHOME 路径也就不足为奇了

但是,当我年轻的时候,我已经习惯了旧的 8.3 格式的 MS/DOS 文件......

我仍然可以在控制台 (CMD.EXE) 窗口中使用DIR /X 在 Windows 7 框中看到(并使用它们)。此格式仅使用 ASCII 大写字符和 tilda (~),因此可以用作解决方法:只需在环境变量 PYTHONHOME 中声明 8.3 路径,然后使用该 8.3 路径启动 python。

顺便说一句,建议 PYTHONHOME 使用既不包含特殊字符也不包含空格的路径。它可以工作,但可能会导致其他模块出现问题

【讨论】:

  • 如果它可以在俄罗斯 Windows 上运行,我完全同意,因为它们具有相应的系统代码页(猜测它的 CP1251)。但它也失败了。
  • 为了完整起见:俄罗斯操作系统的控制台代码页为 866
  • 如果缺少 8.3 名称,请检查它们是否被禁用:fsutil behavior query Disable8dot3 C:。请注意,启用 8.3 名称只会影响随后创建的新文件,而不影响现有文件。您也可以尝试使用mklink 创建仅 ASCII 的硬链接、符号链接或联结。
【解决方案2】:

查看PyImport_ImportModule function version 2.7 给出了这个定义:

PyObject *
PyImport_ImportModule(const char *name)
{
    PyObject *pname;
    PyObject *result;

    pname = PyString_FromString(name);
    if (pname == NULL)
        return NULL;
    result = PyImport_Import(pname);
    Py_DECREF(pname);
    return result;
}

查看PyImport_ImportModule function version 3.5 时给出相同的结果

pname = PyUnicode_FromString(name);

而不是

pname = PyString_FromString(name);

您可以查看the code for PyString_FromStringthe code for PyUnicode_FromString,但似乎很明显 python 2 不使用 unicode 而 python 3 使用,但我无法找到这导致您描述的行为的具体方式/位置。

PyImport_Import(module_name) function (version 2.7) 只使用module_name,如下所示:

r = PyObject_CallFunction(import, "OOOOi", module_name, globals,
                          globals, silly_list, 0, NULL);

推卸责任...

【讨论】:

  • 只是一些背景信息 仅供参考:Python 2 处理 Unicode,但 Python 3 的 Unicode 处理完全重做。Python 2 使用“最佳猜测”解码方法,如果猜错了,一切都将冲出重围。 Python 3 将 Uncode 字符串视为字符串,将 Unicode 编码为字节数组,如果需要,强制您显式处理转换。
  • 我预计问题出在 PyImport_Import 中的某个地方。我猜在其路径中查找带有 unicode 字符的目录会失败。如前所述,我还没有调试它。在这个阶段,至少 latin-1 仍受支持。
猜你喜欢
  • 2017-03-17
  • 2013-06-11
  • 2012-06-29
  • 1970-01-01
  • 1970-01-01
  • 2022-09-27
  • 2018-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多