Windows üzerinde python 2.7.4 kullanma (Not: WinXP - aşağıdaki yorumcu, Win7 üzerinde düzgün çalışmayı önerir), birkaç iş parçacığı oluşturan bir komut dosyası var her biri dosyalara ve çağrılara yeniden yönlendirilmiş stdout/stderr ile Popen aracılığıyla bir çocuk işlemi çalıştırır. Her Popen'in kendi kendi stdout/stderr dosyaları vardır. Her işlemden sonra bazen dosyaları silmek için 'a sahibim (aslında onları başka bir yere taşıyın).Python Popen, Windows'ta çoklu iş parçacıklı - stdout/stderr günlüklerini silemiyor
Tüm bu wait() çağrıları geri gelene kadar stdout/stderr günlüklerini silemediğimi buluyorum. Bundan önce "WindowsError: [Hata 32] işlemi başka bir işlemi tarafından kullanıldığından dosyaya erişemiyor." Görünüşe göre Popen, dosyalarının paylaşılmasa bile, en az bir alt işlemin açık olduğu sürece, stderr dosyalarına bir şekilde tutunmuş gibi görünüyor.
Test kodu aşağıdan kopyalamak için.
C: \ test1.py
import subprocess
import threading
import os
def retryDelete(p, idx):
while True:
try:
os.unlink(p)
except Exception, e:
if "The process cannot access the file because it is being used by another process" not in e:
raise e
else:
print "Deleted logs", idx
return
class Test(threading.Thread):
def __init__(self, idx):
threading.Thread.__init__(self)
self.idx = idx
def run(self):
print "Creating %d" % self.idx
stdof = open("stdout%d.log" % self.idx, "w")
stdef = open("stderr%d.log" % self.idx, "w")
p = subprocess.Popen("c:\\Python27\\python.exe test2.py %d" % self.idx,
stdout=stdof, stderr = stdef)
print "Waiting %d" % self.idx
p.wait()
print "Starting deleting logs %d" % self.idx
stdof.close()
stdef.close()
retryDelete("stderr%d.log" % self.idx, self.idx)
print "Done %d" % self.idx
threads = [Test(i) for i in range(0, 10)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
c: \ test2.py: Bu çalıştırırsanız
import time
import sys
print "Sleeping",sys.argv[1]
time.sleep(int(sys.argv[1]))
print "Exiting",sys.argv[1]
, her retryDelete() dosya erişim hatası üzerinde spin göreceksiniz tüm çocuk süreçleri bitene kadar.
UPDATE: Sorun, stdof ve stdef dosya tanıtıcıları Popen yapıcısına iletilmese bile gerçekleşir. Ancak, Popen kaldırılır ve wait() time.sleep (self.idx) ile değiştirilirse, (siler hemen gerçekleşir) olmaz. Popen'in kendisine aktarılmamış dosya tanımlayıcıları üzerinde bir etkisi olduğu anlaşıldığından bu konunun mirası ele almakla ilgili olup olmadığını merak ediyorum.
GÜNCELLEME: close_fds = Doğru (stdout/stderr yönlendirme yaparken değil Windows üzerinde desteklenen) bir hata verir ve bekleme() çağrısından sonra del p ile POPEN nesneyi silme konuya hiç fark etmez.
UPDATE: Dosyaya tanıtıcılarla işlemler aramak için sysinternals process explorer kullanıldı. Testi sadece 2 diş/çocuk için azaltın ve ikincisini uzun süre açık bırakın. Sapta ara, stderr0.log tutamaçlarına sahip tek işlemin, ona açılan iki tutamağa sahip ana python işlemi olduğunu gösterdi.
GÜNCELLEME: benim şimdiki acil kullanım için, komut satırı alır ve stderr stdout'u parametre olarak log dosyaları/ve yeniden yönlendirilmiş yavru işlem çalıştırarak ayrı komut dosyası oluşturmak için bir geçici çözüm, buldum. Üst öğe, daha sonra bu yardımcı komut dosyasını os.system() ile yürütür. Günlük dosyaları daha sonra başarılı bir şekilde serbest bırakılır ve silinir. Bununla birlikte, hala bu sorunun cevabına cevap verdim. Bana WinXP'ye özgü bir hata gibi geliyor, ama yine de yanlış bir şey yapıyorum.
"stdof" ve "stdef" yi "Popen" e geçirmeniz gerekiyor mu? –
Evet - teşekkürler, Janne. Bununla birlikte, bu düzeltmeden sonra devam eden sorunla ilgisi yoktur. Örneği güncelledim. – Tom
Hmmm - ilginç olsa da. Belki sorun Popen ile ilgili değildir. Muhtemelen aptalca bir şey yapıyorum ... – Tom