web-dev-qa-db-ja.com

.pywおよびpythonwがWindows 7で実行されない

単純な.pyまたは.pyw pythonファイルを実行すると、python.exeタスクマネージャの下に表示されます。

python myApp.py
python myApp.pyw

ただし、コンソールを使用せずにスクリプトを実行しようとすると、スクリプトが実行されていないように見え、python.exeまたはpythonw.exeがタスクマネージャの下に表示されます

pythonw myApp.pyw
pythonw myApp.py

問題をどのようにトラブルシューティングしますか?システムはPython 2.7.8 x64を実行しています。

23
Nyxynyx

tl; dr

  • トラブルシューティングを実行するには、呼び出し時に出力リダイレクトを使用します。

    pythonw myApp.py 1>stdout.txt 2>stderr.txt
    

これは、ファイルstdout.txtprint()などのstdout出力と、ファイルstderr.txtのstderr出力(未処理の例外など)をキャプチャします。 PowerShellから、
cmd /c pythonw myApp.py 1>stdout.txt 2>stderr.txt)。
stdoutをリダイレクトするまさにその行為により、実際にスクリプトが再び機能する可能性がありますifpythonwでの失敗の唯一の理由は、 printの使用(Python 2.xで-下記を参照).
警告:この出力リダイレクト手法は、おそらくnot*.pywスクリプトを呼び出すときに機能します直接(スクリプトファイルパスを渡すのではなく) pythonw.exeに)。 理由がわかっている場合や、うまくいくかどうかをお知らせください。

  • スクリプトを修正するには:

Python 2.xまたは3.xスクリプトの先頭に以下を配置pythonw.exeで実行

import sys, os
if sys.executable.endswith("pythonw.exe"):
  sys.stdout = open(os.devnull, "w");
  sys.stderr = open(os.path.join(os.getenv("TEMP"), "stderr-"+os.path.basename(sys.argv[0])), "w")

これにより、pythonw.exeを使用してスクリプトを実行したときに、次のことが保証されます。

  • print()呼び出しとsys.stdout()への明示的な呼び出しは事実上無視されます(何もしません)。
  • Stderrの出力、未処理の致命的な例外からの出力を含むは、ファイル%TEMP%\stderr-<scriptFileName>に送信されます。 %TEMP%は、一時ファイル用の現在のユーザーのフォルダーを指す標準のWindows環境変数です。

言い換えると、上記のコードを配置した後、スクリプトが%TEMP%\stderr-<scriptFileName>で呼び出されたときに警告なしに失敗した後、ファイルpythonw.exeを確認してください

説明については、読んでください。


Windowsでは、pythonw.exeはGUI/no-UI-at-allスクリプトを起動するためのものです。つまり、標準の入出力ストリーム-sys.stdinsys.stdoutsys.stderrは使用できません。

これには2つの厄介な副作用があります:

  • sing print()-デフォルトでsys.stdoutをターゲットにします-Python 2.x。で例外が発生します
    • この問題はPython 3.xで修正されました。
  • 未処理の例外-2.xのprint()によってトリガーされたものを含む-スクリプトを中止サイレント。にします
    • 例外エラーメッセージはデフォルトでsys.stderrに送られますが、これはこのシナリオでは利用できないものです。

上記のコードはこれらの問題を次のように修正します。

  • stdout出力をnullデバイスに送信し、明示的に、またはprint()を介して暗黙的にsys.stdoutへの出力の試みを事実上無視します。

  • すべてのstderr出力を一時ファイルに送信します。


Python 2.xとPython 3.xの違い:

pythonw.exesys.stdinsys.stdout、およびsys.stderrを使用してスクリプトを実行すると、次のようになります。

  • in Python 2.xinvalidファイル記述子
    • sys.stdoutまたはsys.stderrに書き込もうとしたときのeventual結果は、次の例外です:IOError: [Errno 9] Bad file descriptor
    • 落とし穴:出力バッファリングにより、この例外は、たとえば4Kバイトを出力するまで表示されない場合があります; pythonw.exe-uで(バッファリングされていない出力用に)呼び出すことで、即座にそれを呼び出すことができます。
    • print()は盲目的にsys.stdout(デフォルト)を試行するため、遅かれ早かれこの例外を引き起こします。
  • in Python .x:are set to None
    • これは、sys.stdoutNoneであることがわかったときにno-op(何もしない)を実行する3.x print()関数で補完されるため、print()ステートメントはデフォルトで安全に使用できます。pythonw.exeで実行すると、ステートメントはignoredになります。
    • ただし、sys.stdout.write()およびsys.stderr.write()を使用しようとしても例外が発生することになります。

詳細については こちら を参照してください。

32
mklement0

import sys; sys.stderr = open("errlog.txt", "w")myApp.pyの先頭に追加してみてください。次に、errlog.txtでトレースバックまたはその他のエラーメッセージを探します。

4
Ross Ridge

自分のスクリプトでも同じ問題に直面し、Rossの回答からの出力を追加すると、スクリプトが実際に実行されることがわかりました。

何らかの理由で出力をリダイレクトすると問題が解決するようです。出力をディスクに書き込むことに興味がないので、代わりに/dev/null(または同等のプラットフォーム)に出力しました。

if ( sys.platform == 'win32' and sys.executable.split( '\\' )[-1] == 'pythonw.exe'):
    sys.stdout = open(os.devnull, 'w')
    sys.stderr = open(os.devnull, 'w')

Ifステートメントは、スクリプトがpythonw.exeから起動された場合にのみ発生することを保証します。関連しているかどうかはわかりませんが、他のインポート(import loggingなど)の前に行うことが重要でした。

2
mfitzp

私は同様の問題を抱えていました。

ログファイルに書き込んで段階的にデバッグした後、呼び出しsys.stdout.write()を使用しようとしたステートメントの後でpythonw.exeがクラッシュしたことを発見しました。 pythonw.exeで実行すると、sys.stdoutはNoneになります。

Sys.stdout/stderr/stdinの関数を使用していて、プログラムをpythonw.exeで使用する場合は、「なし」のチェックを追加することをお勧めします。

1
Amol