Python - iddia ve karşı iddia


13

Bir metin dosyasına bir şey yapan bir komut dosyası yazıyorum (ne olsa benim soru için ilgisiz). Bu yüzden dosyaya bir şey yapmadan önce dosyanın var olup olmadığını kontrol etmek istiyorum. Bunu yapabilirim, sorun değil, ama mesele daha çok estetik.

İşte benim kodu, aynı şeyi iki farklı şekilde uygulamak.

def modify_file(filename):
    assert os.path.isfile(filename), 'file does NOT exist.'


Traceback (most recent call last):
  File "clean_files.py", line 15, in <module>
    print(clean_file('tes3t.txt'))
  File "clean_files.py", line 8, in clean_file
    assert os.path.isfile(filename), 'file does NOT exist.'
AssertionError: file does NOT exist.

veya:

def modify_file(filename):
    if not os.path.isfile(filename):
        return 'file does NOT exist.'


file does NOT exist.

İlk yöntem çoğunlukla önemsiz bir çıktı üretir, umursadığım tek şey dosyanın mevcut olmamasıdır.

İkinci yöntem bir dize döndürür, basittir.

Sorularım: Kullanıcının dosyanın mevcut olmadığını bildirmek için hangi yöntem daha iyidir? assertYöntemi kullanmak bir şekilde daha pitonik görünüyor.

Yanıtlar:


34

Bunun yerine üçüncü bir seçenekle devam edersiniz : kullanım raiseve özel bir istisna. Bu yerleşik istisnalardan biri olabilir veya iş için özel bir istisna oluşturabilirsiniz.

Bu durumda, ben kullanırım IOError, ama bir ValueErrorde uygun olabilir:

def modify_file(filename):
    if not os.path.isfile(filename):
        raise IOError('file does NOT exist.')

Belirli bir istisna kullanmak , farklı istisnai durumlar için diğer istisnaları artırmanıza ve arayanın istisnayı zarif bir şekilde ele almasına izin verir.

Tabii ki, birçok dosya işlemleri (gibi open()) kendileri yükseltmek OSErrorzaten; dosyanın var olup olmadığını açıkça ilk test burada gereksiz olabilir.

Kullanmayın assert; python ile -Obayrak çalıştırırsanız , tüm iddialar koddan çıkarılır.


işten çıkarmayla ilgili ilginç bir nokta! Bundan kaçınmayı tavsiye eder misiniz? yani "daha sonra yine başarısız olacak"
Ciprian Tomoiagă

1
@ CiprianTomoiagă: testlerde neden ikiye katlandınız? Bir sonraki satır modify_file()ise with open(filename) as f:, o IOErrorzaman da yükseltilir. Ve daha yeni Python sürümleri, bu API'yı kullanan bir geliştiriciye yardımcı olabilecek alt sınıflarında IOError( FileNotFoundErrorözellikle akla gelen) daha fazla ayrıntı sağladı . Kod kendi kontrollerini yapar ve yükseltirse, IOErrorbu yararlı detay kaybolacaktır.
Martijn Pieters

@MartijnPieters, "testleri neden ikiye katlasın?" open () başarısız olduğunda ilk kontrol istisnadan daha hızlı olduğunda ne olur? örneğin, bir dosyanın varlığını kontrol ederken açmaya çalışmaktan ve daha sonra bunu yapmamaktan daha hızlıdır.
Marcel Wilson

1
@MarcelWilson: Hayır, çünkü G / Ç yapan bir yönteme göre mikro optimizasyon yaparsınız. Dakikalar içinde hiçbir ince ayar yapmak Python semantiği G / Ç'nin daha hızlı gitmesini sağlar ve yalnızca okunabilirliği ve sürdürülebilirliği incitir. Daha fazla etkisi olan alanlara odaklanın diyebilirim.
Martijn Pieters

12

assertişlevi yerine getiren programlayıcının kullanıcının aksine hata yaptığı durumlar için tasarlanmıştır . Kullanımı asserto surette emin bir programcı test sırasında doğru işlevini kullandığından emin ama sonra üretimde dışarı soymak için izin verir.

Kodu aracılığıyla bu yolu kullandığınızdan emin olmanız gerektiğinden ve genellikle sorunu ifüretimde ayrı bir ifadeyle ele almak istediğiniz için değeri biraz sınırlıdır . assert"Bir kullanıcı vurursa bu soruna yardımcı olmak istiyorum, ancak bir geliştirici vurursa, bu işlevi yanlış çağıran kodu düzeltmek için sert çökmesini istiyorum" gibi durumlarda en yararlıdır.

Özel durumunuzda, eksik bir dosya neredeyse kesinlikle bir kullanıcı hatasıdır ve bir istisna oluşturarak ele alınmalıdır.


5

Gönderen UsingAssertionsEffectively

Kontrol isinstance () aşırı kullanılmamalıdır: bir ördek gibi quacks, belki de gerçekten olup olmadığını çok derin sorgulamaya gerek yoktur. Bazen orijinal programcı tarafından beklenmedik değerleri iletmek yararlı olabilir.

İddiayı ortaya koymayı düşünecek yerler:

checking parameter types, classes, or values
checking data structure invariants
checking "can't happen" situations (duplicates in a list, contradictory state variables.)
after calling a function, to make sure that its return is reasonable 

Genel olarak, bir şeyler ters giderse, onu mümkün olan en kısa sürede tamamen açık hale getirmek istiyoruz.

Girildiği noktada yanlış verileri yakalamak, sorun çıkardığında daha sonra oraya nasıl geldiğini bulmaktan daha kolaydır.

İddialar, birim testlerin veya sistem testlerinin yerine geçmez, aksine bir tamamlayıcıdır. İddialar bir nesnenin veya fonksiyonun dahili durumunu incelemenin temiz bir yolu olduğundan, dış davranışı inceleyen bir kara kutu testine "ücretsiz" bir açık kutu yardımı sağlarlar.

İddialar gerektiğini değil bulunamadı ediliyor çünkü kötü kullanıcı girişi veya işletim sistemi / böyle bir dosya olarak çevre arızaları, oluşabilir başarısızlık durumları için teste kullanılabilir. Bunun yerine, bir istisna oluşturmalı veya bir hata mesajı veya uygun olanı yazdırmalısınız. İddiaların yalnızca programın kendi kendini sınaması için kullanılmasının önemli bir nedeni, iddiaların derleme sırasında devre dışı bırakılabilmesidir.

Python -O seçeneği ile başlatılırsa, onaylamalar kaldırılır ve değerlendirilmez. Bu nedenle kod, iddiaları yoğun bir şekilde kullanıyor ancak performans açısından kritikse, sürüm sürümlerinde bunları kapatmak için bir sistem vardır. (Ancak gerçekten gerekli olmadıkça bunu yapmayın. Bazı hataların yalnızca bir müşteri makineyi kullandığında ortaya çıktığı bilimsel olarak kanıtlanmıştır ve biz de orada yardımcı olmak için iddialarda bulunmak istiyoruz. :-))

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.