Feature #4592

Tempfileを直接保存したい

Added by Takeyuki FUJIOKA almost 3 years ago. Updated 12 months ago.

[ruby-dev:43412]
Status:Assigned
Priority:Normal
Assignee:Yukihiro Matsumoto
Category:lib
Target version:next minor

Description

=begin
Tempfileは一時ファイルなので、プロセスが消えたり、#closeすると、
ファイルが消えてしまいます。
Tempfileのデータを保存するために
一旦読みだして、書き込み用に別ファイルを開いて、
そこに書きこまなければいけません。
これが小さいファイルだったらいいのですが、
大きいファイルになると、
Tempfile#save みたいなメソッドを用意して、
closeと同時に保存ができると、
読みだして書きこむという無駄をなくすことができます。
10MB程度だったらいいのですが、500MとかのTempfileだと
かなり有効なメソッドだと思います。

#save とか #save! とか、何がいいかは議論の余地があると思います。
=end

History

#1 Updated by Sakuro OZAWA almost 3 years ago

=begin
#close(real=false)したあと、#path を使って、保存したいところに File#rename とか、File#link を使うとよいと思います。

=end

#2 Updated by Sakuro OZAWA almost 3 years ago

=begin
先頭が # だと丸ごと見えなくなるのか…

((%#close(real=false)%))したあと、#path を使って、保存したいところに File#rename とか、File#link を使うとよいと思います。

=end

#3 Updated by Kenta Murata almost 3 years ago

=begin
Tempfile#mv(path) というメソッドを追加するパッチを書いてみました。
https://gist.github.com/933915

File.rename してるので、元のファイルが無くなっちゃいますし、
元のファイルと同じファイル名のまま維持したい場合は使えなかったりします。

=end

#4 Updated by Sakuro OZAWA almost 3 years ago

=begin
FileUtilsと間違えた。renameやlinkはFileのクラスメソッドでした。

=end

#5 Updated by Shyouhei Urabe almost 3 years ago

=begin
* closeと同時というのを諦め、closeのちょっと後でよければ、普通にmvできるのではないでしょうか。
irb(main):001:0> f = Tempfile.new('')
=> #File:/tmp/20110421-7098-1bvjwc0
irb(main):002:0> f.puts("foobar")
=> nil
irb(main):003:0> f.close; File.rename(f, "tmp.txt")
=> 0
irb(main):008:0> File.read("tmp.txt")
=> "foobar\n"
* /tmpとRubyのカレントディレクトリが別パーティションだったら、どのみちコピーは発生するのではないでしょうか。
* Tempfileを保存したいというのはTempfileの意味からして本末転倒なのではないでしょうか。

といった感想を抱きました。
=end

#6 Updated by Takeyuki FUJIOKA almost 3 years ago

=begin
卜部さんの言うとおりなのですが、ユースケースを書きますと、
Railsもcgi.rbも巨大なファイルをアップロードしたときは
tempfileにファイルを保存します。
これを保存したいとなったときに、
tempfileから読みだして、別ファイルをオープンして
書きこむという手間とメモリが必要なので、
tempfileに入っているんだから、そのままリネームでもして
保存出来ればいいのになと思ったのでした。

ちなみに卜部さんのやり方ももちろんOKですが、
私的にはHTTP Requestをまたいで使いたいので、
tempfileを消えないようにだけするという対応でも
OKなのでした。tempfile名をセッションにでも入れて、
次のリクエストでまた開くということをやりたかったです。
=end

#7 Updated by Yusuke Endoh about 2 years ago

  • Description updated (diff)
  • Status changed from Open to Assigned
  • Assignee set to Yusuke Endoh

#8 Updated by Akira Tanaka about 2 years ago

remove_finalizer とか、save とかよりももうちょっと長い名前がいいんじゃないかなぁ、と思います。

#9 Updated by Koichi Sasada about 2 years ago

(2012/03/25 15:33), akr (Akira Tanaka) wrote:

remove_finalizer とか、save とかよりももうちょっと長い名前がいいんじゃないかなぁ、と思います。

 mv なり hardlink などして,File を返すインターフェースとかだと良かった
りしないでしょかね.「消されない」Tempfile ってのに違和感がありまして.

 Tempfile#mv(filepath) #=> File とか,cp でもいいか.

--
// SASADA Koichi at atdot dot net

#10 Updated by Yusuke Endoh about 2 years ago

どういう意味でこのチケットを自分にアサインしたか忘れてしまったのですが。

shyouhei (Shyouhei Urabe) wrote:

  • closeと同時というのを諦め、closeのちょっと後でよければ、普通にmvできるのではないでしょうか。 irb(main):001:0> f = Tempfile.new('') => #File:/tmp/20110421-7098-1bvjwc0 irb(main):002:0> f.puts("foobar") => nil irb(main):003:0> f.close; File.rename(f, "tmp.txt") => 0 irb(main):008:0> File.read("tmp.txt") => "foobar\n"

これは、GC タイミングによっては失敗しますよね。(f.close の直後で GC)
また、rename 後に元のファイル名と同じファイルを作ったら、この tempfile が
GC される際に消されてしまう危険があると思います。
よって、workaround としては推奨しかねるものだと思います。

  • /tmpとRubyのカレントディレクトリが別パーティションだったら、どのみちコピーは発生するのではないでしょうか。

気にするなら、Tempfile 生成ディレクトリを自分で指定すればいいと思います。

  • Tempfileを保存したいというのはTempfileの意味からして本末転倒なのではないでしょうか。

これは個人の感覚の問題だと思いますが、「temporary だけど、うまく行けば
永続化するつもり」というのは私はいいかなあと思いました。

akr (Akira Tanaka) wrote:

remove_finalizer とか、save とかよりももうちょっと長い名前がいいんじゃないかなぁ、と思います。

Tempfile#persist とか、秋葉原の開発者会議で出た案でしたっけ。

Yusuke Endoh mame@tsg.ne.jp

#11 Updated by Yusuke Endoh about 2 years ago

  • Assignee changed from Yusuke Endoh to Yukihiro Matsumoto

mame (Yusuke Endoh) wrote:

どういう意味でこのチケットを自分にアサインしたか忘れてしまったのですが。

思い出しました。開発者会議で出た内容をまとめて matz に振るのでした。
しかし開発者会議で出た内容を正確に覚えてないんですが、

  • ユースケースは理解できる
  • 卜部さんの workaround は推奨されない
  • 良い API・名前はなんだろう

くらいだったと思います。間違ってたら正してください > 参加者

matz が直接判断しなくても、tempfile.rb のメンテナになってくれる人が
いれば判断できると思います。
まあメンテナになるのに matz の承認が必要ですが。

あと訂正。

これは、GC タイミングによっては失敗しますよね。(f.close の直後で GC)

これは間違いでした。f の参照が残っているので GC されることはありません。
でも race condition の問題はあるので、やはり推奨はされない、という話
だったと思います。

Yusuke Endoh mame@tsg.ne.jp

#12 Updated by Koichi Sasada about 2 years ago

(2012/04/02 21:50), mame (Yusuke Endoh) wrote:

くらいだったと思います。間違ってたら正してください > 参加者

 間違ってないですが,個人的には Tempfile インスタンスのまま消えないのは
不思議なので,Tempfile#xxx #=> File みたいなメソッド xxx があるといいん
じゃないかなぁ,と.って, に書いてるじゃん.

--
// SASADA Koichi at atdot dot net

#13 Updated by Yusuke Endoh over 1 year ago

  • Target version set to next minor

#14 Updated by Takeyuki FUJIOKA 12 months ago

Tempfile#to_file!(path)

とか?

自分の提起チケットなので反応してみました。

いろいろあった結果、担当がMatzになっていますね。

Also available in: Atom PDF