質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

2227閲覧

python sys.stdout.close() とは

akiyama3284pga

総合スコア186

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2022/01/16 12:43

編集2022/01/18 05:53

pythonのプログラム内におきまして、

sys.stdout.close()

p1 = subprocess.Popen(['ls'], stdout=subprocess.PIPE) p2 = subprocess.Popen(["grep", "txt"], stdin=p1.stdout, stdout=subprocess.PIPE) p1.stdout.close() output = p2.communicate()[0]

のようにclose()というものがあると思うのですが、
両者は同じものなのでしょうか?

後者ではclose()の行が無くても意図する動作は得られました。

また、その機能につきましても調べてみても適格な答えが見つかりませんでしたので
ご質問させていただきました。

よろしくお願いいたします。<(_ _)>

自分のためのメモ

# 指定したプログラム(orファイル)でファイルを開くのが、 # popen()、つまりpopen()は内部で新規のopen(, 'rb')のようなことをしている。 # openされた新規臨時ファイルには、渡されたプログラムの標準出力が書き込まれる。 # shファイルなどを渡されても同様それを実行した標準出力を書き込む。 # stdout引数にPIPEが指定されていると、作成されるインスの変数stdoutにそのファイルオブが # セットされる。 p1 = subprocess.Popen(['ls'], stdout=subprocess.PIPE) # バイナリモードの場合は読み込み(openのrb引数)はio.BufferedReaderファイルオブが返る。 print(p1.stdout) # <_io.BufferedReader name=4> ※バイナリ指定のファイルオブ # name=4の4は通常にopen()使用した際はファイル名になるので、popenが付けてるファイル名 # この数値は被ることがないようになっているようだ。 # 当然read()やreadline()などファイルオブが持つメソを使える。(同じオブだから当然) # ただしcommunicateなどはpopen独自のものだから、p1.communicate()のように使う。 # ファイルの利用が終われば close(ファイルオブのインスメソ)を使ってファイルオブジェクトを閉じる後処理をする。 # これをしなければどんなリスクがあるのかは、f.close()しない場合と全く同じこと。 p1.stdout.close() # close()した後にprint(p1.stdout.read())としても当然ValueError: read of closed file # ただし、seek(0)で元に戻して再度read()しようとしてみるとio.UnsupportedOperation: File or # stream is not seekable.になった。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ioをクローズするという意味では同じです。クローズされる物は違います。

2つめのコードのp1.stdout.close()は、「使わないパイプの口はクローズしておこう」という意図で書かれているのだと思いますが(もしくは必要だと勘違いして書いたか)、
p2 = subprocess.~~の行でコピーされた後は使ってないパイプの口なので、クローズしても、放置しても他の部分の処理には関係ないです。

投稿2022/01/16 15:16

編集2022/01/16 15:19
otn

総合スコア84421

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akiyama3284pga

2022/01/17 03:52

いつも的確にご回答ありがとうございます。 なぜ該当行が無くても意図する動作となったのか、その理屈を理解することができました。<(_ _)>
guest

0

ベストアンサー

ppaulさんの回答の通りではありますが、僕なりの回答を

プログラムは外部とやりとりする必要があります。
やり取りする方法は、動作しているシステムやプログラミング言語によっていろいろな種類があるのですが、その1つに「openして使うもの」があります。
ファイルはそうです。 UNIXの場合、キーボードやターミナルもそうして使うものになっています(ファイルと同じ扱いになっている)。質問にあるstdoutは基本的にはこのターミナルにつながっています。

さて、その、openして使えるようになったものは、一般的に、そのプログラミング(プロセス)に利用権があるので、他のプログラム(プロセス)は使うことができません。なので、使い終ったら返す必要があるのです。それがclose処理です。

使たものをもう使わないと宣言するのがcloseですから、書かなくてもそのプログラムは困らないことが多いです。また、そのプログラムが終了したときには、基本的には自動でcloseされます。(物によってはだめなものもあります)

投稿2022/01/16 14:08

TakaiY

総合スコア12657

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akiyama3284pga

2022/01/17 05:41 編集

憶測からご回答ありがとうございます。 まさに自分が知りたかった部分でございます。 基本的にファイルはopen(), close()でファイルディスクリプタを open(利用権の取得=確保) => close (利用権の破棄=解放)して利用する。 そして、UNIXの場合キーボードやターミナルもファイルして使うものになっている。 利用権を確保したままのプロセスが動いていると他プロセスから同じものの利用権は確保できない。 つまり、 後者 subprocess.popen() は子プロセスを開くことをしている。 動作中のプログラムも一つのプロセスとなり、その(親)プロセス内で子プロセスを開始するのが、 subprocess.popen()やrun()である。(両者の違いは非同期かどうか) p1.stdout.close()した後に、p1.stdout.read()などするとValueError: read of closed fileとなる。 これは当然取得した(openした)もの(Popenインスタンスの標準出力)をclose()したから。 前者 pythonは新たなプロセス(program)が開始される際に毎回sys.stdout(標準出力先)をディスプレイに設定する。 sys.stdout.close() を実行しますとprint('..')してもterminal出力されなくなる。 つまりは、そのプログラム(プロセス)内で設定されたsys.stdoutの設定をclose(ファイルディスクリプタを開放)したということ。 だから新たな別プログラム内では当然print()は正常に動く。 というような認識で大まかには...よろしいでしょうか?
TakaiY

2022/01/17 10:36

基本的にはその認識で問題ないと思います。 pythonはlinuxのプロセス管理をベースにして作られていますので、他のOSでは想定とは違う挙動をすることがありますから、そのあたりのシビアな処理をするときはもっと深い理解が必要になるかもしれませんが。
akiyama3284pga

2022/01/18 04:14

ご回答ありがとうございます。 ファイルオブジェクト関連は継承などが非常に入り組んでいるようで、付け焼刃の知識では全体像をがっちりと理解するのは帰って誤解や遠回りを生むように感じましたので、しっかりドキュメントなどを読み込んでいきたいと存じます。 結局は今回の質問は、 ...stdout.close() は f.close() と同じくファイルオブジェクトをclose()しているのだということが理解できていればよかったようです。 最後までお付き合いいただきありがとうございます。<(_ _)>
guest

0

akiyama3284pgaさんが考える「同じ」が何を意味するかによります。

たとえば、以下の二つの+は同じでしょうかという質問があったとします。
Pythonの処理系にとって以下の二つの+は同じです。しかし、これを同じだと考えない人もいるでしょう。

Python

1>>> 1 + 2 23 3>>> 'a' + 'b' 4'ab'

そうすると、この二つが「同じ」だと答えても「同じでない」と答えても、質問者と回答者が違うことを考えていてコミュニケーションが成立しない可能性があります。

今回のご質問は、どういう意味で「同じ」なのかが定義されていないと回答のしようがない質問ですので、質問を編集して意味を明確にしてください。

投稿2022/01/16 13:06

ppaul

総合スコア24666

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問