SORU
20 Temmuz 2009, PAZARTESİ


Sürekli Yakut dış sürecin STDOUT okuma

Blender sonra çizgi çıktı blender hattı tarafından verilen bir GUI içinde bir ilerleme çubuğu güncelleme için işleyecek olan yakut bir komut ile komut satırından çalıştırmak istiyorum. Okumak için lazım olan blender dış süreç olduğu çok önemli değil.

Blender süreci hala çalışıyorsa mesajları blender normalde kabuk parmak izi ilerleme yakalamak edebilmek için görünmüyor olabilir, ve bir kaç yol denedim. Ben hep blender stdout erişim gibi görünüyorsonrablender hala çalışırken değil iken, çıkıldı.

İşte başarısız bir girişim örneği. Blender süreci çıktıktan sonra oluyor ve blender çıkışının ilk 25 satırları yazdırmak, ama:

blender = nil
t = Thread.new do
  blender = open "| blender -b mball.blend -o //renders/ -F JPEG -x 1 -f 1"
end
puts "Blender is doing its job now..."
25.times { puts blender.gets}

Düzenleme:

Biraz daha net yapmak için, komut yürütmesini blender kabuk çıkış akışı, ilerleme (tamamlandı parçası 1-16 vb) gösteren geri verir. Herhangi bir "olur" çıktı blender kapatıncaya kadar engellendi. çağrı gibi görünüyor Sorunu hala blender blender çıkışı shell için baskı olarak çalışırken bu çıktı erişebilir.

CEVAP
22 Temmuz 2009, ÇARŞAMBA


Benim bu sorunu çözme konusunda bazı başarılar elde ettim. Burada herkes benzer bir sorun yaşıyorsanız, bu sayfayı bulur diye detayları, bazı açıklamalar. Ama eğer ayrıntılar için umurunda eğerburada kısa cevap:

PTY kullanın.aşağıdaki şekilde (tabii ki kendi komut ile) spawn:

require 'pty'
cmd = "blender -b mball.blend -o //renders/ -F JPEG -x 1 -f 1" 
begin
  PTY.spawn( cmd ) do |stdout, stdin, pid|
    begin
      # Do stuff with the output here. Just printing to show it works
      stdout.each { |line| print line }
    rescue Errno::EIO
      puts "Errno:EIO error, but this probably just means "  
            "that the process has finished giving output"
    end
  end
rescue PTY::ChildExited
  puts "The child process exited!"
end

Veişte uzun cevapçok çok detay:

Asıl sorun gibi görünüyor, eğer bir süreç değil açıkça floş onun stdout, o zaman her şey yazılmış stdout olduğunu tamponlu yerine gönderilen, o kadar işlemi yapılır, böylece en aza indirmek için IO (bugörünüşe görebirçok C kütüphaneleri, verimi maksimize böylece daha sık IO üzerinden yapılan bir uygulama ayrıntı). Eğer stdout düzenli olarak temizler, böylece süreci rahatlıkla değiştirebilirsiniz, o zaman bir çözüm olur. Benim durumumda, blender, yani benim gibi tam bir çaylak kaynağını değiştirmek için biraz korkutucu oldu.

Ama kabuğundan bu işlemler çalıştırdığınızda, gerçek zamanlı olarak kabuk stdout görüntüler ve stdout tamponlu görünmüyor. Benim inandığım başka bir işlem çağrıldığında tamponlu, ama eğer bir kabuk ile uğraştığı, stdout, ne zaman adet görülür.

Bu davranış, gerçek zamanlı olarak toplanması gerekir kimin çocuğu işlemi olarak ruby işlemi ile görülebilir. Sadece bir komut dosyası oluşturmak, rastgele.rb, aşağıdaki satırı:

5.times { |i| sleep( 3*rand ); puts "#{i}" }

Sonra ruby bir senaryo olarak görüyor ve çıkış geri dönmek için:

IO.popen( "ruby random.rb") do |random|
    random.each { |line| puts line }
  end
end

Ama aynı anda daha sonra tahmin edebileceğiniz gibi gerçek zamanlı olarak sonuç alamadım göreceksiniz. STDOUT eğer rastgele çalıştırırsanız bile tamponlu ediliyor.kendinizi rb, tamponlu değil. Bu rasgele blok içinde STDOUT.flush ifadesini ekleyerek çözülebilir.rb. Ama eğer kaynağını değiştirmek değil, bu geçici bir çözüm. Süreci dışarıdan harcayabilirsin.

Eğer alt süreci gerçek zamanlı shell için baskı olursa, o zaman gerçek zamanlı olarak Ruby ile bunu yakalamak için bir yolu olmalı. Ve yoktur. PTY modülü kullanmak için ruby core inanıyorum (1.8.6 neyse) dahil. Üzücü şey belgelenmiş değil. Ama bazı örnekler neyse ki buldum.

İlk olarak, PTY ne olduğunu açıklamak için, pseudo terminal anlamına geliyor. Temelde, ruby komut dosyası sadece bir kabuk komutu yazılı olan gerçek bir kullanıcı ise alt süreci olarak kendini sunmak için izin verir. Sadece bir kullanıcı bir kabuk ile süreci (STDOUT, bu durumda tamponlu olmamak gibi) başladığında ortaya çıkan herhangi bir değişmiş davranış ortaya çıkar. Başka bir süreç, bu sürecin başladığını gerçeği gizliyor tamponlu olmak değil, gerçek zamanlı, STDOUT toplamak için izin verir.

Bu rastgele bir iş yapmak için.çocuk gibi rb komut dosyası, aşağıdaki kodu deneyin:

require 'pty'
begin
  PTY.spawn( "ruby random.rb" ) do |stdout, stdin, pid|
    begin
      stdout.each { |line| print line }
    rescue Errno::EIO
    end
  end
rescue PTY::ChildExited
  puts "The child process exited!"
end

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • dcigs

    dcigs

    9 EYLÜL 2006
  • undrmyumbrellaa

    undrmyumbrel

    25 Temmuz 2012
  • FusioNGamiing

    FusioNGamiin

    10 Temmuz 2007