トホホな疑問(23) 今、StdOutどこ向いている?

JosephHalfmoon

今までそんなシチュエーションにならなかったのが不思議なくらいなのです。Windowsのバッチファイルの中で呼び出すつもりのPythonのスクリプトを書いていて、

標準出力がコンソールに向いているのか、どこかにリダイレクトされているのか知りたい

と思ったのです。この歳になるまでそんな事をついぞ考えないで生きてきたのですから、まずは幸せな人生であった、というべきでしょう。sysモジュールか何かで簡単に知れるんでないかい、と思ったのが間違いでした。

確かにPythonのsysモジュールには以下のような

  • sys.stdout
  • sys.__stdout__

標準出力を表すファイル・オブジェクトが存在します。特に、後者は「起動時のsys.stdout」を保存することになっていて、sys.stdoutをどこかにリダイレクトしても元に戻せるようになっていたりします。一瞬、リダイレクトされている時に、この二つを比べれば違いあるじゃん、とか思いましたが、

単なる気の迷い

であることに気付きました。だって、Python起動するコマンドラインが書かれているバッチファイルそのものの出力がリダイレクトされているのかも知れないのです、Pythonのスクリプトが走ったときには、全てが終わっています。未練がましく、バッチの出力をリダイレクトしているときと、そうでないときでsys.stdoutの型が変化するかと見てみましたが、勿論、変わりませぬ。

import sys
type(sys.stdout)
<class '_io.TextIOWrapper'>

まあね、このオブジェクトがラップしている先を掘っていったらいずれは分かるに違いありませんが、そんな気力はありません。大体、バッチレベルでリダイレクトされているのだから、cmd.exe、ウインドウズの機能でそういうことが分からんもんかしら、と調べてみました。ただ、「リダイレクト」などで調べると標準ストリームのリダイレクトよりも、URLのリダイレクトなどネットねたがヒットしてきます。これはいけないと思って、stdout とか標準ストリームもキーワードに加えていると、ヒットしてくるのは、「どうやってリダイレクトするか」、ぶっちゃけ

> とか 2>&1 とか

の世界、そうされている内側にいて、外がどうなっているのか知りたいんだよ、私は。ようやく見つけました。総武ソフトウエア推進所様の以下の記事であります。

標準ストリームがリダイレクトされているかどうかを調べる

まさに、私が知りたかったことズバリ。そこに記されている情報によれば、

.NET Framework 4.5 以降で使えるIsOutputRedirectedプロパティ

使えば分かるのでした。Windows上のPythonで調べていても埒が明かない感じだったので、ここはありがたく上記で逃げよう。上記の記事は、VBだったのですが、私は、C#派なので、バッチ内で使えるような小さなコマンドラインプログラムを書いてみました。こんな感じ。

こいつを使えば、バッチファイルの標準出力がどこ向いているか分かる筈。テスト用のバッチファイル hogehoge.bat がこちら、

@echo off
isStdoutRedirected
if ERRORLEVEL 1 (
	SET IS_REDIRECT=YES
) ELSE (
	SET IS_REDIRECT=NO
)
python foo.py

そして肝心の「行先を知りたい」と思っているPythonスクリプトのテスト用ファイル foo.py がこちら。

import os
if "IS_REDIRECT" in os.environ:
    print("IS_REDIRECT = {0}".format(os.environ["IS_REDIRECT"]))
else:
    print(os.environ)

リダイレクトしないときと、した時で反応を見てみましょう。

$ hogehoge
CONSOLE.
IS_REDIRECT = NO


$ hogehoge >a.txt


$ type a.txt
REDIRECTED.
IS_REDIRECT = YES

まあね、目的は達しましたが、釈然としないです。Python書いていた筈が、いつの間にかC#になっている。なんとかならないものかなあ、トホホ。

トホホな疑問(22) 駅のホームのWiMax?

トホホな疑問(24) Python3.8.0、CHCP関係ない?