FAQ по Python под Windows

Как запустить программу на Python под Windows?

Это не всегда простой вопрос. Если вы уже знакомы с запуском программ из командной строки Windows, то все будет казаться очевидным; в противном случае вам может понадобиться немного больше подсказок.

Если вы не используете какую-то интегрированную среду разработки, вам придется набирать команды Windows в так называемом «окне командной строки». Обычно такое окно можно создать из строки поиска по запросу cmd. Вы должны быть в состоянии распознать, когда вы запустили такое окно, потому что вы увидите «командную строку» Windows, которая обычно выглядит следующим образом:

C:\>

Буква может быть другой, а после нее может идти что-то еще, так что вы с тем же успехом можете увидеть что-то вроде:

D:\YourName\Projects\Python>

в зависимости от того, как был настроен ваш компьютер и что еще вы недавно делали с ним. Как только вы запустили такое окно, вы уже на пути к запуску программ на Python.

Вы должны понимать, что ваши скрипты Python должны быть обработаны другой программой, называемой интерпретатором Python. Интерпретатор читает ваш скрипт, компилирует его в байткоды, а затем выполняет байткоды, чтобы запустить вашу программу. Как же организовать работу интерпретатора с вашим Python?

Во-первых, нужно убедиться, что командное окно распознает слово «py» как инструкцию для запуска интерпретатора. Если вы открыли командное окно, попробуйте ввести команду py и нажать клавишу return:

C:\Users\YourName> py

Вы должны увидеть что-то вроде:

Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:04:45) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

Вы запустили интерпретатор в «интерактивном режиме». Это означает, что вы можете вводить утверждения или выражения Python в интерактивном режиме, и они будут выполняться или оцениваться, пока вы ждете. Это одна из самых сильных возможностей Python. Проверьте это, введя несколько выражений по своему выбору и посмотрев на результаты:

>>> print("Hello")
Hello
>>> "Hello" * 3
'HelloHelloHello'

Многие используют интерактивный режим как удобный, но в то же время программируемый калькулятор. Когда вы захотите завершить интерактивную сессию Python, вызовите функцию exit() или удерживайте клавишу Ctrl, пока вводите Z, а затем нажмите клавишу «Enter», чтобы вернуться в командную строку Windows.

Вы также можете обнаружить, что в меню «Пуск» есть пункт Start ‣ Programs ‣ Python 3.x ‣ Python (command line), в результате чего вы видите приглашение >>> в новом окне. В этом случае окно исчезнет после вызова функции exit() или ввода символа Ctrl-Z; Windows выполняет в этом окне единственную команду «python» и закрывает его, когда вы завершаете работу интерпретатора.

Теперь, когда мы знаем, что команда py распознается, вы можете передать ей свой сценарий Python. Вам нужно будет указать абсолютный или относительный путь к сценарию Python. Допустим, ваш Python-скрипт находится на рабочем столе и имеет имя hello.py, а командная строка открыта в вашем домашнем каталоге, поэтому вы видите что-то похожее на:

C:\Users\YourName>

Теперь вы попросите команду py передать ваш скрипт в Python, набрав py, а затем путь к вашему скрипту:

C:\Users\YourName> py Desktop\hello.py
hello

Как сделать скрипты Python исполняемыми?

В Windows стандартная программа установки Python уже связывает расширение .py с типом файла (Python.File) и дает этому типу файла команду open, которая запускает интерпретатор (D:\Program Files\Python\python.exe "%1" %*). Этого достаточно, чтобы скрипты исполнялись из командной строки как „foo.py“. Если вы хотите, чтобы сценарий можно было выполнить, просто набрав „foo“ без расширения, вам нужно добавить .py в переменную окружения PATHEXT.

Почему Python иногда так долго запускается?

Обычно Python запускается под Windows очень быстро, но иногда появляются сообщения об ошибках, когда Python вдруг начинает долго запускаться. Это еще больше озадачивает, потому что Python прекрасно работает на других системах Windows, которые, похоже, настроены одинаково.

Проблема может быть вызвана неправильной конфигурацией программного обеспечения для проверки на вирусы на проблемной машине. Известно, что некоторые антивирусные сканеры создают накладные расходы при запуске на два порядка больше, если сканер настроен на мониторинг всех чтений из файловой системы. Попробуйте проверить конфигурацию антивирусных программ на ваших системах, чтобы убедиться, что они действительно настроены одинаково. McAfee, настроенный на сканирование всех операций чтения файловой системы, является особым нарушителем.

Как сделать исполняемый файл из сценария Python?

Список инструментов, которые можно использовать для создания исполняемых файлов, см. в Как создать автономный двоичный файл из сценария Python?.

Является ли файл *.pyd тем же самым, что и DLL?

Да, файлы .pyd - это dll, но есть несколько отличий. Если у вас есть DLL с именем foo.pyd, то у нее должна быть функция PyInit_foo(). Вы можете написать Python «import foo», и Python будет искать foo.pyd (а также foo.py, foo.pyc) и, если найдет его, попытается вызвать PyInit_foo() для его инициализации. Вы не связываете свой .exe с foo.lib, так как это заставит Windows потребовать присутствия DLL.

Обратите внимание, что путь поиска foo.pyd - это PYTHONPATH, а не тот же путь, который Windows использует для поиска foo.dll. Кроме того, foo.pyd не обязательно должен присутствовать для запуска вашей программы, в то время как если вы связали свою программу с dll, то dll необходима. Конечно, foo.pyd необходим, если вы хотите сказать import foo. В DLL связь объявляется в исходном коде с помощью __declspec(dllexport). В .pyd связь определяется в списке доступных функций.

Как встроить Python в приложение Windows?

Встраивание интерпретатора Python в приложение для Windows можно описать следующим образом:

  1. Не не встраивайте Python в .exe-файл напрямую. В Windows Python должен быть DLL, чтобы справиться с импортом модулей, которые сами являются DLL. (Это первый ключевой недокументированный факт.) Вместо этого ссылайтесь на pythonNN.dll; обычно он устанавливается в C:\Windows\System. NN - это версия Python, число, например «33» для Python 3.3.

    Вы можете связываться с Python двумя разными способами. Связывание во время загрузки означает связывание с pythonNN.lib, а связывание во время выполнения означает связывание с pythonNN.dll. (Общее примечание: pythonNN.lib - это так называемый «импорт lib», соответствующий pythonNN.dll. Она просто определяет символы для компоновщика).

    Связывание во время выполнения значительно упрощает параметры связей; все происходит во время выполнения. Ваш код должен загружать pythonNN.dll с помощью подпрограммы Windows LoadLibraryEx(). Код также должен использовать процедуры доступа к данным в pythonNN.dll (то есть API Python на языке C) с помощью указателей, полученных с помощью процедуры Windows GetProcAddress(). Макросы могут сделать использование этих указателей прозрачным для любого кода на языке C, который вызывает подпрограммы в C API Python.

  2. Если вы используете SWIG, то легко создадите «модуль расширения» для Python, который сделает данные и методы приложения доступными для Python. SWIG сделает за вас практически все сложные детали. В результате вы получите код на Си, который вы подключите в свой .exe-файл (!) Вам **не нужно создавать DLL-файл, и это также упрощает подключение.

  3. SWIG создаст функцию init (функцию на языке C), имя которой зависит от имени модуля расширения. Например, если имя модуля - leo, то функция init будет называться initleo(). Если вы используете теневые классы SWIG, как и должно быть, функция init будет называться initleoc(). Она инициализирует в основном скрытый вспомогательный класс, используемый теневым классом.

    Причина, по которой вы можете подключить код на Си в шаге 2 к вашему .exe-файлу, заключается в том, что вызов функции инициализации эквивалентен импорту модуля в Python! (Это второй ключевой недокументированный факт).

  4. Короче говоря, вы можете использовать следующий код для инициализации интерпретатора Python с вашим модулем расширения.

    #include <Python.h>
    ...
    Py_Initialize();  // Initialize Python.
    initmyAppc();  // Initialize (import) the helper class.
    PyRun_SimpleString("import myApp");  // Import the shadow class.
    
  5. Есть две проблемы с C API Python, которые станут очевидными, если вы используете компилятор, отличный от MSVC - компилятора, использованного для сборки pythonNN.dll.

    Проблема 1: Так называемые функции «очень высокого уровня», принимающие аргументы FILE *, не будут работать в среде с несколькими компиляторами, поскольку понятие struct FILE у каждого компилятора будет разным. С точки зрения реализации это очень низкоуровневые функции.

    Проблема 2: SWIG генерирует следующий код при создании оберток для функций void:

    Py_INCREF(Py_None);
    _resultobj = Py_None;
    return _resultobj;
    

    Увы, Py_None - это макрос, который расширяется до ссылки на сложную структуру данных под названием _Py_NoneStruct внутри pythonNN.dll. Опять же, этот код будет неудачным в многокомпиляторной среде. Замените этот код на:

    return Py_BuildValue("");
    

    Возможно, можно использовать команду SWIG %typemap для автоматического внесения изменений, хотя мне не удалось добиться этого (я полный новичок в SWIG).

  6. Использование сценария оболочки Python для создания окна интерпретатора Python внутри приложения Windows - не самая лучшая идея; получаемое окно не будет зависеть от оконной системы вашего приложения. Вместо этого вам (или классу wxPythonWindow) следует создать «родное» окно интерпретатора. Подключить это окно к интерпретатору Python очень просто. Вы можете перенаправить ввод-вывод Python на _любой_ объект, поддерживающий чтение и запись, так что все, что вам нужно, это объект Python (определенный в вашем модуле расширения), который содержит методы read() и write().

Как запретить редакторам вставлять табуляции в исходный текст Python?

FAQ не рекомендует использовать табуляции, а руководство по стилю Python, PEP 8, рекомендует использовать 4 пробела для распределенного кода Python; это также значение по умолчанию в Emacs python-mode.

В любом редакторе смешивать табуляции и пробелы - плохая идея. MSVC в этом отношении ничем не отличается и легко настраивается на использование пробелов: Возьмите Tools ‣ Options ‣ Tabs, для типа файла «По умолчанию» установите «Размер табуляции» и «Размер отступа» на 4 и выберите радиокнопку «Вставить пробелы».

Python поднимает IndentationError или TabError, если смешанные табуляции и пробелы вызывают проблемы с лидированием пробельных символов. Вы также можете запустить модуль tabnanny для проверки дерева каталогов в пакетном режиме.

Как проверить нажатие клавиши без блокировки?

Используйте модуль msvcrt. Это стандартный модуль расширения, специфичный для Windows. Он определяет функцию kbhit(), которая проверяет наличие удара по клавиатуре, и getch(), которая получает один символ без эха.

Как решить проблему отсутствия api-ms-win-crt-runtime-l1-1-0.dll?

Это может произойти на Python 3.5 и более поздних версиях при использовании Windows 8.1 или более ранних версий без установки всех обновлений. Сначала убедитесь, что ваша операционная система поддерживается и имеет актуальные обновления, а если это не поможет решить проблему, посетите Microsoft support page, чтобы получить руководство по ручной установке обновления C Runtime.