Windows 上の Python FAQ
***********************


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 でなければなりません。(ドキュメ
   ント化されていない重大な事実の一つ目です。)代わりに、
   "python*NN*.dll" とリンクしてください; 普通はそれは
   "C:\Windows\System" にインストールされています。 *NN* は Python バ
   ージョンで Python 3.3 であれば "33" のような数字です。

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

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

   Borland note: まず "python*NN*.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()" を定義します。
