Bir dosyaya stdout bağlı bir terminal oluşturuyorsunuz, böylece terminallerin yaptıkları normal eko-geri, ekran yerine dosyaya gönderiliyor.
Im spawn
böyle doğrudan kullanılmak üzere tasarlanmıştır emin olun: pty
kütüphane bir alt süreç oluşturmak için pty.fork()
sunar ve Stdin/stdout için bir dosya tanıtıcı ile döner. Ancak bunu kullanmak için çok daha fazla koda ihtiyacınız olacak.
Seçenek 1: bir dosyaya kökenli komutun çıktısını gönderiyor umurumda tüm, o zaman yapabiliyorsa
iki kolay seçenekler heres, sen
spawn
ile yaptığınız şimdiki sorunu aşmak için Bu gibi görünecektir
çalıştırın::
start to stdout only
hello
complete to stdout only
(i piton için boru ve
here
dosyaları tek gömlekleri adında tercih) 210
, girişin (merhaba yazdım) ve baskı ifadelerinin sonucunun ekrana gittiğini gösterir. Out.txt dosyasının içeriği şu şekilde olacaktır: Yalnızca yazdığınız şey budur.
Seçenek 2: diğer taraftan sen kökenli komut çıktısı etrafında piton çıktı içermesini dışarı dosyayı istiyorum, o zaman gibi biraz daha karmaşık bir şey, gerek:
python <(cat << EOF
import sys
import pty
import os
old_stdout = sys.stdout
sys.stdout = myfdout = os.fdopen(4,"w")
print 'start to out file only'
myfdout.flush()
pty.spawn(sys.argv[1:])
print 'complete to out file only'
sys.stdout = old_stdout
EOF
) bash -c 'cat >&4' 4>out.txt
hangi edecek dışarı dosya içerecek
hello
ama:
0 sadece (yazdığınız her ne yani) çalıştırın terminale bu çıkışı
Arka plan: python pty
kütüphanesi güçlüdür: onun python bağlı bir terminal aygıtı oluşturma stdout ve stdin. İdenin en çok kullandığını düşünmek, gerçek stdin/stdout'un etkilenmemesi için pty.fork()
aramasını kullanacaktır.
Sizin durumunuzda, kabuğunuzda, python işleminin stdout'unu bir dosyaya yönlendirdiniz. Sonuçta oluşan pty, bu nedenle, stdout'un dosyaya eklenmiş olmasını sağlamıştır, böylece stdut'a geri eklenmiş stdin'in normal hareketi yeniden yönlendirilmiştir. Düzenli stdout (ekran) hala yerindeydi ancak yeni pty tarafından kullanılmıyordu.
Seçenek yukarıda 1 için temel fark Pty oluşturulan hala (gerçek terminali Stdout'a açık bir bağlantı vardır, böylece yankı çalıştığında için, pty.spawn
çağrısı içinde bir yerde ortaya Stdout'a yeniden yönlendirme taşımaktır yazarken stdin)
Seçenek 2 için fark piton içine girince, keyfi bir dosya tanımlayıcı üzerinde ikinci bir kanal (yani dosya tanımlayıcı 4) oluşturmak ve stdout yerine bu kullanmaktır ve oluşturduğunuz zaman doğuştan işleminiz (yani, aynı süreç tanımlayıcısına sahip olduğunuz işlemin stdout'unu yeniden yönlendirin)
Bu farkların her ikisi de, pty.spawn
'un stdout'unun değiştirilmesinden veya gerçek terminalden ayrılmasından kaynaklanan piti önler. Bu, stdin'in doğru bir şekilde çalışmasını sağlar.
pty
kütüphane kullanımı ve daha fazla kontrol elde paketleri vardır ama bunların çoğu pty.fork()
kullanmak (ve ilginçtir ben kimse aslında pty.spawn
kullanır sığınak bulundu) bir örnek İşte
DÜZENLEMEYİ bulacaksınız Bu questionpty.fork()
için bazı iyi bağlantıları vardır
import sys
import pty
import os
import select
import time
import tty
import termios
print 'start'
try:
pid, fd = pty.fork()
print 'forked'
except OSError as e:
print e
if pid == pty.CHILD:
cmd = sys.argv[1]
args = sys.argv[1:]
print cmd, args
os.execvp(cmd,args)
else:
tty.setraw(fd, termios.TCSANOW)
try:
child_file = os.fdopen(fd,'rw')
read_list = [sys.stdin, child_file]
while read_list:
ready = select.select(read_list, [], [], 0.1)[0]
if not ready and len(read_list) < 2:
break
elif not ready:
time.sleep(1)
else:
for file in ready:
try:
line = file.readline()
except IOError as e:
print "Ignoring: ", e
line = None
if not line:
read_list.remove(file)
else:
if file == sys.stdin:
os.write(fd,line)
else:
print "from child:", line
except KeyboardInterrupt:
pass
EDIT: pty.fork() kullanma
GÜNCELLEME: kodunda bazı yorumlar vermeliydim pty.fork()
örnek nasıl çalışır:
çevirmeni pty.fork()
çağrısı yürütür , processesing ikiye böler: Her iki görünen iki konu şimdi vardır Sadece pty.fork()
aramasını yaptım.
Bir iş parçacığı, başlangıçta içinde bulunduğunuz (üst) ve bir tanesi yeni bir iş parçacığı (alt öğe).ebeveyn olarak
, pid
ve fd
çocuğun işlem kimliği ve teh çocuğun stdin ve stdout ünitesine bağlı bir dosya decriptor ayarlanır: ebeveyn de, size karşı yazılanların okuduğunuz fd
doğru okunduğunda oğullar stdout; fd
'a yazdığınızda childs'ın stdinine yazıyorsunuz. Şimdi, ebeveynin içinde, diğer iş parçacığıyla stdout/stdin üzerinden iletişim kurabiliyoruz. Çocukta pid
0 olarak ayarlanmış ve fd
ayarlanmamış. Eğer ebeveyn iş parçacığıyla konuşmak istiyorsak, ebeveynin bunu yapabileceği ve yapması gerektiğini bilerek stdin/stdout üzerinden okuyabilir ve yazabiliriz.
İki iş parçacığı, bu noktadan aynı kodu yürütecek, ancak ebeveyn veya çocuk iş parçacığının pid
'daki değere göre olup olmadığını anlatabiliriz. Çocuğumuzda ve ebeveyneğimizde farklı şeyler yapmak istiyorsak, o zaman çocuğu bir kod yolunu ve ebeveynini farklı bir kod yoluna indiren bir koşullu ifadeye ihtiyacımız var. Bu hat ne Thats:
çocukta if pid == pty.CHILD:
#child thread will execute this code
....
else
#parent thread will execute this code
...
, biz sadece yeni bir pty yeni komut yumurtlamaya istiyorum. os.execvp
biz bu yöntemle ancak esasen onun ebeveyn de, gerçek Stdin bağlamanız gerekir aynı anda Yani fd`
. And the parent can write to the command via pty by writing to
fd pty.spawn()'. This means the child stdin/stdout are now connected to the command you wanted via a pty. IMmportantly, any input or output from the command (or the pty for that matter) will be available to the parent thread by reading from
olarak/stdout bir terminal olarak pty üzerinde daha fazla kontrole sahip olacak çünkü kullanılır çocuk stdin/stdout'a fd
no'lu telefondan okuma ve yazma yoluyla. Artık ana kodun yaptığı şey (else
bölüm). Gerçek stdin üzerinde ortaya çıkan herhangi bir veri fd
'a yazılmıştır. fd
'dan (ebeveyn tarafından) okunan veriler, stdout'a yazılır. Artık ebeveyn iş parçacığının yaptığı tek şey, gerçek stdin/stdout ve fd arasında proxy yapıyor. Girdiğin ve çıktı aldığın bir şeyle programlı bir şekilde yapmak istediysen, bunu yapacağın yer burası.
tty.setraw(fd, termios.TCSANOW)
Bu eko-geri yaparak durdurmak için çocukta pty anlatmak için bir yoludur:
ebeveyn olur tek şey bu çağrıdır.
Bu başlangıçta yapıyorduk sorunu çözer: (girişinizi sürecine geçmeden önce yani) Normal eko-geri yerinde olduğundan - - - Yerel terminali sadece ana iş parçacığı bağlanır arasında stdout süreç yönlendirilebilir - çocuk süreç gibi görünüyor onun stdin
yerel eko-geri yapamaz çekildiği bildirildi - Eğer Terminal stdout ne yaparsak çocuk sürecinin ait stdin/stdout'ta herhangi bir etkisi yoktur Çok fazla açıklama var - eğer herhangi bir açıklık için düzenleme var mı?
solution1 seçeneği ve option2 benim için çalışmaz çünkü dış python işlemi için (yani, diğer programları arayan/çoğaltan) stdout dosyası bir dosyaya/boruya yönlendirilir ve bu benim kontrolüm altında değildir. Bu şekilde başka biri tarafından çağrılır, sadece benim kontrolüm altında çalıştırılan python betiğine sahibim). Bu yüzden çıktıyı iç süreçlere yönlendirip seçemiyorum. (Ama evet, bu özgürlüğe sahip olsaydım, seçenek1 ve 2 kabul edilebilir olurdu) –
Son örnek kodu çalıştırdım (** EDIT ** içinde) ve bu aslında benim sorunumu çözüyor gibi görünüyor. Ama hala nasıl çalıştığını kafamın etrafına sarmak için mücadele ediyorum :( –
@ abhishek-kedia Ive bir açıklama ekledi – spacepickle