# Windows 上の Python FAQ

目次

- Windows 上の Python FAQ

  - Python プログラムを Windows で動かすにはどうしますか？

  - Python スクリプトを実行可能にするにはどうしますか？

  - Python の起動に時間がかかることがあるのはなぜですか？

  - どうすれば Python スクリプトを EXE に出来ますか?

  - `*.pyd` ファイルは DLL と同じですか？

  - Python を Windows アプリケーションに埋め込むにはどうしたらいいですか？

  - エディタが Python ソースにタブを勝手に挿入しないようにするにはどうしますか？

  - ブロックすることなく押鍵を検出するにはどうしますか？

## Python プログラムを Windows で動かすにはどうしますか？

これは必ずしも単純な質問ではありません。Windows コマンドラインからプログラムを実行するのに慣れてしまっている場合は、全て明らかなことに思えるでしょう; そうでない場合は、もう少し手引きが必要でしょう。

ある種の統合開発環境を使っているのでなければ、最終的には "DOS ウィンドウ" や "コマンドプロンプト" などと色々に呼ばれているものに、 Windows コマンドをタイプすることになるでしょう。 通常そういうウィンドウは検索バーで `cmd` を検索して起動します。 通常は次のような見た目の Windows の "コマンド プロンプト" が現れるので、ウィンドウが起動したのが分かるはずです:

    C:\>

この文字は異なっていたり、続きがあったりするので、コンピュータの設定や、あなたが最近何をしたかに依って、このようになっていることもあるでしょう:

    D:\YourName\Projects\Python>

このようなウィンドウさえ開けば、Python プログラムを動かす手順は順調に進みます。

Python スクリプトは Python インタプリタ と呼ばれる別のプログラムで処理されなければならないということを、理解する必要があります。インタプリタはスクリプトを読み込み、バイトコードにコンパイルし、バイトコードを実行しプログラムを走らせます。では、インタプリタが Python スクリプトを取り扱うためには、どんな用意をするのでしょうか?

まず最初に、コマンドウィンドウに "py" という単語がインタプリタを起動する指示であると認識させる必要があります。 コマンドウィンドウを開いたら、 `py` というコマンドを入力し、リターンキーを叩いてください。:

    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 コマンドプロンプトに戻ってください。

スタート ‣ すべてのプログラム ‣ Python 3.x ‣ Python (command line) のような項目がスタートメニューに見付かるかもしれません。 これを起動すると、新しいウィンドウに `>>>` というプロンプトが見られるでしょう。その場合、 `exit()` 関数を呼び出すか `Ctrl-Z` を入力するとウィンドウは閉じます; Windows は 1 つの "python" コマンドをウィンドウで実行していて、インタプリタを終了させたときに、そのウィンドウを閉じます。

`py` コマンドが認識されていることが確認できたので、 Python スクリプトを与えられるようになりました。 そのためには Python スクリプトの絶対パスあるいは相対パスを与える必要があります。 Python スクリプトがデスクトップにあり、 `hellp.py` という名前で、ちょうど良いことにコマンドプロンプトがホームディレクトリを開いていると仮定しましょう。そうすると次のような表示が見られます:

    C:\Users\YourName>

ここまで来れば `py` の後ろにスクリプトのパスを入力することで、 Python にスクリプトを渡すよう `py` コマンドに命令できます:

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

## Python スクリプトを実行可能にするにはどうしますか？

Windows では、標準の Python インストーラはすでに .py 拡張子をあるファイル型 (Python.File) に関連付け、そのファイル型にインタプリタを実行するオープンコマンド (`D:\Program Files\Python\python.exe "%1" %*`) を与えます。コマンドプロンプトから 'foo.py' としてスクリプトを実行可能にするにはこれで十分です。スクリプトを拡張子なしで 'foo' とだけタイプして実行したいのなら、PATHEXT 環境変数に .py を加えてください。

## Python の起動に時間がかかることがあるのはなぜですか？

通常 Python は Windows でとても早く起動しますが、ときどき Python が急にスタートアップに時間がかかるようになったというバグレポートがあります。更に複雑なことに、Python は同様に設定された他の Windows システムではきちんと動くのです。

この問題はそのマシンのウイルス対策ソフトウェアの設定ミスによって起こされることがあります。ウイルススキャナの中には、ファイルシステムからの全ての読み込みを監視するように設定した場合に、二桁のスタートアップオーバーヘッドを引き起すことが知られているものがあります。あなたのシステムのウイルススキャンソフトウェアの設定を確かめて、本当に同様に設定されていることを確実にしてください。

## どうすれば Python スクリプトを EXE に出来ますか?

See cx_Freeze and py2exe, both are distutils extensions that allow you to create console and GUI executables from Python code.

## `*.pyd` ファイルは DLL と同じですか？

はい、.pyd ファイルは dll と同じようなものですが、少し違いがあります。`foo.pyd` という名前の DLL があったとしたら、それには関数 `PyInit_foo()` が含まれていなければなりません。そうすれば Python で "import foo" を書けて、Python は foo.pyd (や foo.py、foo.pyc) を探して、あれば、`PyInit_foo()` を呼び出して初期化しようとします。Windows が DLL の存在を必要とするのと違い、.exe ファイルを foo.lib にリンクするわけではありません。

なお、foo.pyd を検索するパスは PYTHONPATH であり、Windows が foo.dll を検索するパスと同じではありません。また、プログラムを dll にリンクしたときはプログラムの実行に dll が必要ですが、foo.pyd は実行には必要はありません。もちろん、 `import foo` したいなら foo.pyd は必要です。DLL では、リンクはソースコード内で `__declspec(dllexport)` によって宣言されます。.pyd では、リンクは使える関数のリストで定義されます。

## Python を Windows アプリケーションに埋め込むにはどうしたらいいですか？

Python インタプリタを Windows app に埋め込む方法は、次のように要約できます:

1. あなたの .exe 内に直接 Python を取り込んでビルド しないで 下さい。Windows では、それ自身が DLL になっているようなモジュールのインポートを処理するために、Python は DLL でなければなりません。(ドキュメント化されていない重大な事実の一つ目です。)代わりに、 `pythonNN.dll` とリンクしてください; 普通はそれは `C:\Windows\System` にインストールされています。 NN は Python バージョンで Python 3.3 であれば "33" のような数字です。

   Python には、load-time に、または run-time にリンクできます。load-time なリンクは、 `pythonNN.lib` に対してリンクするもので、run-time なリンクは `pythonNN.dll` に対してリンクするものです。(一般的な注意: `pythonNN.lib` は `pythonNN.dll` に対するいわゆる "インポートライブラリ" です。これは単にリンカに対するシンボルを定義します。)

   run-time なリンクは、リンクの選択を大いに単純化します。全ては実行時に行われます。コードは Windows の `LoadLibraryEx()` ルーチンで `pythonNN.dll` をロードしなければなりません。コードはまた、Windows の `GetProcAddress()` ルーチンで得られるポインタで、 `pythonNN.dll` (すなわち、Python の C API)のルーチンとデータへアクセスしていなければなりません。マクロによって、このポインタを Python の C API のルーチンを呼び出す任意の C コードに通して使えます。

   Borland note: まず `pythonNN.lib` を Coff2Omf.exe で OMF フォーマットに変換してください。

2. SWIG を使えば、app のデータとメソッドを Python で使えるようにする Python "拡張モジュール"を簡単に作れます。SWIG は雑用を殆どやってくれるでしょう。結果として、.exe ファイル の中に リンクする C コードができます(！)。DLL を作 _らなくてもよく_、リンクも簡潔になります。

3. SWIG は拡張の名前に依る名前の init 関数 (C 関数) を作ります。例えば、モジュールの名前が leo なら、init 関数の名前は initleo() になります。SWIG shadow クラスを使ったほうがよく、そうすると init 関数の名前は initleoc() になります。これは shadow クラスが使うほとんど隠れた helper クラスを初期化します。

   ステップ 2 の C コードを .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. Python の C API には、pythonNN.dll をビルドするのに使われたコンパイラ MSVC 以外のコンパイラを使うと現れる二つの問題があります。

   問題 1: コンパイラによって struct FILE に対する概念が異なるため、FILE * 引数を取るいわゆる "超高水準" 関数は、多コンパイラ環境で働きません。実装の観点から、これらは超 _低_ 水準関数になっています。

   問題 2: SWIG は void 関数へのラッパを生成するときに以下のコードを生成します:

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

   ああ、Py_none は pythonNN.dll 内の _Py_NoneStruct という複雑なデータ構造に展開するマクロです。また、このコードは他コンパイラ環境では失敗します。このコードを次のように置き換えてください:

       return Py_BuildValue("");

   これで、SWIG をまだ仕事に使えない (私は SWIG の完全な初心者です) 私でも、SWIG の `%typemap` コマンドを使って自動的に変更できるようになります。

6. Python シェルスクリプトを使って Windows app 内から Python インタプリタウィンドウを掲示するのはいい方法ではありません。そのように表示されるウィンドウは app のウィンドウシステムとは関係ありません。むしろ "ネイティブな" インタプリタウィンドウを (wxPythonWindow を使ったりして) 作るべきです。そのウィンドウを Python インタプリタにつなぐのは簡単です。Python の i/o は読み書きをサポートする _どんな_ オブジェクトにもリダイレクトできるので、read() と write() メソッドを含む (拡張モジュールで定義された) Python オブジェクトさえあればいいのです。

## エディタが Python ソースにタブを勝手に挿入しないようにするにはどうしますか？

この FAQ ではタブを使うことを勧めません。Python スタイルガイド PEP 8 では、配布される Python コードにはスペース 4 つを使うことを推奨しています。これは Emacs の python-mode のデフォルトでも同じです。

いかなるエディタでも、タブとスペースを混ぜるのは良くないです。 MSVC も全く同じ立場であり、スペースを使うようにする設定が簡単にできます。 Tools ‣ Options ‣ Tabs を選択し、ファイルタイプの "デフォルト" の "タブ幅" と "インデント幅" に 4 を設定して、 "スペースを挿入する" のラジオボタンを選択してください。

Python は、もしタブとスペースが混在していることで先頭の空白に問題がある場合、`IndentationError` または `TabError` を送出します。 `tabnanny` モジュールを実行することで、ディレクトリーツリーをバッチモードでチェックすることができます。

## ブロックすることなく押鍵を検出するにはどうしますか？

`msvcrt` モジュールを使ってください。これは標準の Windows 専用拡張モジュールです。これはキーボードが打たれているかを調べる関数 `kbhit()` と、反響することなく一文字を得る `getch()` を定義します。