Python с нелатинским 1 путем PYTHONHOME

В моем случае я внедрил Python в свое приложение. Когда путь к моему приложению содержит символ, отличный от латинского 1, Py_Initialize вызывает exit(1) внутри (дополнительная информация позже).

Поэтому я проверил, можно ли воспроизвести это с помощью стандартного исполняемого файла интерпретатора.

Python-2.7.x в Windows, похоже, не работает, когда путь PYTHONHOME содержит символ вне кодировки latin-1. Проблема в том, что модуль сайт не может быть найден и импортирован. Поскольку умлауты, похоже, работают, в чем здесь фактическое ограничение? Поддерживается ли только латиница-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)
         ^

Любые идеи?

Предыстория:

Я еще не изучал код, но 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.7: https://github.com/enthought/Python-2.7.3/blob/master/Python/pythonrun.c#L725

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


person HelloWorld    schedule 19.05.2016    source источник
comment
Вы пробовали вместо этого использовать Python 3? Они переделали обработку Unicode, и она стала намного чище. Я рекомендую на самом деле использовать 3 всякий раз, когда вы можете, и 2, только если вам нужно.   -  person A. L. Flanagan    schedule 25.05.2016
comment
В Python 3 это (должно) работать/с, да. Я должен придерживаться Python 2, потому что это версия, которую мы встроили в наше программное обеспечение, хотя это изменится в будущем.   -  person HelloWorld    schedule 26.05.2016
comment
Не могли бы вы рассказать, как вы встраиваете Python в свое приложение? вызывая его из C/C++? какой механизм вы используете? А вы устанавливаете PYTHONHOME? если да то как его настроить? В качестве примечания, поведение OS FS по отношению к путям Unicode немного различается в Windows, Mac и Linux/POSIX. И способ справиться с этим в CPython 2 иногда требует немного возни... Хотя я несколько раз успешно боролся с этим.   -  person Philippe Ombredanne    schedule 26.05.2016
comment
Используя Py_Initialize,... из C API. Я пробовал PYTHOMHOME и соответствующие функции C (Py_SetPath, Py_SetPythonhome, ...) безуспешно. Кстати, Python 2.7 (без встраивания) также не работает, если он установлен по указанным путям.   -  person HelloWorld    schedule 26.05.2016
comment
MS Windows отличается от OS X тем, что там базовым набором символов является UTF-16. Для обратного кода он также предоставляет ANSI API, который использует однобайтовые строки, но не может представлять весь диапазон Unicode. Я почти уверен, что Python 2 никогда не будет обновлен для использования API Win32, полностью поддерживающего Unicode, поэтому любые хлопоты бесполезны, если вы хотя бы не обновитесь до Python 3.   -  person Ulrich Eckhardt    schedule 27.05.2016


Ответы (2)


Я думаю, проблема в том, что внутри Python2 обрабатывает все как байтовые строки в системной кодировке платформы, которая (в Западной Европе) CP1252 является вариантом Latin-1. Поэтому неудивительно, что он не может правильно обработать путь PYTHONHOME, содержащий другие символы.

Но когда я был моложе, я привык к старому доброму формату файлов MS/DOS 8.3...

Я все еще вижу (и использую их) в окне Windows 7 с DIR /X в окне консоли (CMD.EXE). В этом формате используются только символы верхнего регистра ASCII и тильда (~), поэтому его можно использовать в качестве обходного пути: просто объявите путь 8.3 в переменной среды PYTHONHOME и запустите python с этим путем 8.3.

Кстати, для PYTHONHOME рекомендуется использовать путь, который не содержит ни специальных символов, ни пробелов. Это может работать, но может вызвать проблемы с другими модулями.

person Serge Ballesta    schedule 19.05.2016
comment
Я был бы полностью согласен, если бы это работало на русской Windows, потому что у них есть соответствующая системная кодовая страница (угадайте, что это CP1251). Но и там не получается. - person HelloWorld; 19.05.2016
comment
Для полноты картины: кодовая страница консоли 866 для русской ОС. - person HelloWorld; 19.05.2016
comment
Если имена 8.3 отсутствуют, проверьте, отключены ли они: fsutil behavior query Disable8dot3 C:. Обратите внимание, что включение имен 8.3 повлияет только на новые файлы, созданные впоследствии, а не на существующие файлы. Вы также можете попробовать использовать mklink для создания жесткой ссылки только для ASCII, символической ссылки или соединения. - person Eryk Sun; 21.05.2016

Глядя на функцию PyImport_ImportModule версии 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 версии 3.5, выдает то же самое кроме как с

pname = PyUnicode_FromString(name);

вместо

pname = PyString_FromString(name);

Вы можете посмотреть код для PyString_FromString и код для PyUnicode_FromString, но кажется очевидным, что python 2 не используйте unicode и python 3, но я не смог найти, как/где именно это приводит к описанному вами поведению.

Функция PyImport_Import(module_name) (версия 2.7) использует только module_name как так:

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

переложить ответственность...

person hkBst    schedule 25.05.2016
comment
Просто немного предыстории: Python 2 использует Unicode, но обработка Unicode была полностью переделана для Python 3. Python 2 использовал метод декодирования методом наилучшего предположения, и если он угадал неправильно, весь ад вырвался на свободу. Python 3 обрабатывает строки Uncode как строки, а закодированные Unicode — как массивы байтов, что вынуждает вас явно обрабатывать преобразование, если это необходимо. - person A. L. Flanagan; 25.05.2016
comment
Я предполагаю, что проблема была обнаружена где-то в PyImport_Import. Я предполагаю, что поиск каталогов с символами Юникода в их пути не удался. Как уже упоминалось, я не отлаживал его. По крайней мере, latin-1 все еще поддерживается на данном этапе. - person HelloWorld; 26.05.2016