2013-04-24 13 views
32

Alt işlem - çağrı, check_call, check_output tarafından sağlanan işlevler hakkında bilgi veriyorum ve her birinin nasıl çalıştığını ve birbirlerinden nasıl farklılaştığını anladım. aşağıdaki gibi, Şu anda check_output kullanıyorum, bu yüzden Stdout'a erişebilir ve durum yakalamak için "blok deneyin" kullandı:Altprogram çağrısından çıkış kodunu ve stderr'i alın

# "cmnd" is a string that contains the command along with it's arguments. 
try: 
    cmnd_output = check_output(cmnd, stderr=STDOUT, shell=True, timeout=3, universal_newlines=True);       
except CalledProcessError:                         
    print("Status : FAIL")                         
print("Output: \n{}\n".format(cmnd_output))                     

bir istisnası atılır zaman içine çalıştırıyorum konudur " cmnd_output" başlatılmadı ve stderr'e erişimi yok ve ben aşağıdaki hata iletisi alıyorum: istisna neden olduğu

print("Output: \n{}\n".format(cmnd_output)) 
UnboundLocalError: local variable 'cmnd_output' referenced before assignment 

Ben buluyorsun öyle 'üzerinde değişiklik yapmadan hemen aka atama kurtarmak için check_output' try bloğunda "cmnd_output" olarak. Yanlışım varsa lütfen düzelt.

Stderr'e erişebilmem için herhangi bir yol var mı (çıkışa gönderilirse tamam) ve çıkış koduna erişiminiz var. Çıkış kodu istisna dışında istisna dışında çıkış/teslim başarısızlığı için manuel olarak kontrol edebilirim.

Teşekkür ederiz, Ahmed.

cevap

44

bu sürümü deneyin: Aşağıdaki satır sadece try ifadesinden üstünde ekleyin çalışacak

import subprocess 
try: 
    output = subprocess.check_output(
     cmnd, stderr=subprocess.STDOUT, shell=True, timeout=3, 
     universal_newlines=True) 
except subprocess.CalledProcessError as exc: 
    print("Status : FAIL", exc.returncode, exc.output) 
else: 
    print("Output: \n{}\n".format(output)) 

Bu şekilde çağrının başarılı yalnızca çıktı yazdırılır. CalledProcessError durumunda, dönüş kodunu ve çıktıyı yazdırırsınız.

+0

Müthiş. Bu sadece mükemmel çalıştı. Teşekkür ederim. –

+2

Bu hatayı alıyorum: 'ret = subprocess.check_output (cmd, stderr = STDOUT, kabuk = True)' 'NameError: global adı 'STDOUT' tanımlı değil ' – ARH

+5

@ARH, https: //docs.python. org/3/library/subprocess.html # subprocess.STDOUT – warvariuc

-2

Neden denemeden önce değişken cmnd_output başlatılamıyor? Bu şekilde beklediğiniz gibi çalışacaktır.

cmnd_output = '' 
+0

Stdout (ve ayrıca stderr) içeriği tarafından başlatılacak cmnd_output'a ihtiyacım var.Bu, programın çıkış kodunun sıfır olmadığı durumlar dışında çoğu durumda gerçekleşir. –

+0

Tam olarak, bir istisna söz konusu olduğunda kodunuz istisnayı yazdıracaktır ve değişkende hiçbir şey olmayacaktır. Ancak, normal olarak çalıştırıldığında (istisna yok), cmnd_output değerlerini alırsınız. – n3rV3

32

kabul çözümü stdout ve stderr karıştırma Tamam olduğu durumda kapsar, ancak durumlarda hangi alt süreç (hangi nedenden olursa olsun) çıkışına (yani olmayan bir başarısız çıkış için stdout için EK OLARAK stderr kullanmaya karar kritik olmayan bir uyarı), daha sonra verilen çözüm istenmeyebilir. Eğer JSON dönüştürme gibi cikislara ek işlem yapıyor olacak ve siz stderr karıştırmak eğer

Örneğin, daha sonra genel işlem çıkış nedeniyle katma stderr çıkış saf JSON olmayacak çünkü başarısız olur . Önerilen çözümlerin

cmd_args = ... what you want to execute ... 

pipes = subprocess.Popen(cmnd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
std_out, std_err = pipes.communicate() 

if pipes.returncode != 0: 
    # an error happened! 
    err_msg = "%s. Code: %s" % (std_err.strip(), pipes.returncode) 
    raise Exception(err_msg) 

elif len(std_err): 
    # return code is 0 (no error), but we may want to 
    # do something with the info on std_err 
    # i.e. logger.warning(std_err) 

# do whatever you want with std_out 
# i.e. json.loads(std_out) 
+0

Çok kullanışlıdır. Bu benim kullanım durumum. stdout hedefim tarafından bir hata çıktısından daha fazla bir günlük çıkışı olarak kullanılır. Bu arada, 'stderr = subprocess.PIPE' sağlama zorunluluğuna yorum yapabilir misiniz? Bunu ek boru olmadan başka mesajlar gördüm ve neden emin değilim. – KobeJohn

+0

python 2.7 için en azından bu kabuk eklerseniz = kabukları True = True –

0

İkisi ya stderr stdout'u/karıştırın veya check_output olarak kullanmak oldukça basit olmadığı Popen kullanın:

Ben bu durumda çalışmak için aşağıdaki buldum. biz stderr yakalanan beri, bu örnekte

import sys 
import subprocess 

try: 
    subprocess.check_output(cmnd, stderr=subprocess.PIPE) 
except subprocess.CalledProcessError as e: 
    print('exit code: {}'.format(e.returncode)) 
    print('stdout: {}'.format(e.output.decode(sys.getfilesystemencoding()))) 
    print('stderr: {}'.format(e.stderr.decode(sys.getfilesystemencoding()))) 

, bu kullanılabildiğine: basitçe yakalama bir boru kullanarak Stderr eğer check_output kullanırken Ancak, aynı şeyi başarmak ve/ayrı stderr stdout'u tutabilir istisnanın stderr özniteliği (boru ile yakalamadan, sadece None olur).

İlgili konular