Python'da iddiaları devre dışı bırakın


Yanıtlar:


80

Python'da iddiaları nasıl devre dışı bırakırım?

Tek bir işlemi, ortamı veya tek bir kod satırını etkileyen birden çok yaklaşım vardır.

Her birini gösteriyorum.

Tüm süreç için

Kullanılması -Obayrağı (sermaye O) bir işlemdeki tüm assert ifadeleri devre dışı bırakır.

Örneğin:

$ python -Oc "assert False"

$ python -c "assert False"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError

Devre dışı bırakmakla, onu takip eden ifadeyi de çalıştırmadığını kastettiğime dikkat edin:

$ python -Oc "assert 1/0"

$ python -c "assert 1/0"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

Çevre için

Bu bayrağı ayarlamak için bir ortam değişkeni de kullanabilirsiniz.

Bu, ortamı kullanan veya miras alan her süreci etkileyecektir.

Örneğin, Windows'ta ortam değişkenini ayarlama ve ardından temizleme:

C:\>python -c "assert False"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError
C:\>SET PYTHONOPTIMIZE=TRUE

C:\>python -c "assert False"

C:\>SET PYTHONOPTIMIZE=

C:\>python -c "assert False"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError

Unix'te aynı ( ilgili işlevsellik için set ve unset kullanarak )

Kodda tek nokta

Sorunuza devam edin:

bir iddia başarısız olursa, bir AssertionError atmasını değil, devam etmesini istiyorum.

Başarısız olan kodun kullanılmasını istiyorsanız, kontrol akışının onaylamaya ulaşmamasını sağlayabilirsiniz, örneğin:

if False:
    assert False, "we know this fails, but we don't get here"

veya onaylama hatasını yakalayabilirsiniz:

try:
    assert False, "this code runs, fails, and the exception is caught"
except AssertionError as e:
    print(repr(e))

hangi yazdırır:

AssertionError('this code runs, fails, and the exception is caught')

ve ele aldığınız noktadan devam edeceksiniz AssertionError.

Referanslar

Gönderen belgeler :assert

Bunun gibi bir iddia ifadesi:

assert expression #, optional_message

Eşdeğerdir

if __debug__:
    if not expression: raise AssertionError #(optional_message)

Ve,

yerleşik değişken __debug__, optimizasyon istendiğinde Truenormal koşullar altındadır False(komut satırı seçeneği -O).

ve Ötesi

'A atamalar __debug__yasa dışıdır. Yerleşik değişkenin değeri, yorumlayıcı başladığında belirlenir.

Kullanım belgelerinden:

Temel optimizasyonları açın. Bu, derlenmiş (bayt kodu) dosyalar için dosya adı uzantısını .pyc'den .pyo'ya değiştirir. Ayrıca bkz. PYTHONOPTIMIZE.

ve

PYTHONOPTIMIZE

Bu boş olmayan bir dizeye ayarlanırsa, -Oseçeneği belirtmeye eşdeğerdir . Bir tam sayıya ayarlanırsa, -Obirden çok kez belirtmeye eşdeğerdir .


'Kodda tek nokta' durumunda başarısız olan kodu atlamak mümkün olabilir mi? False'a ayarlamayı denedim __debug__ama buna izin verilmiyor.
Matthijs

1
@Matthijs, kontrol akışının ona ulaşmamasını sağlayabilir (örn. if False: assert False) Veya Onaylama hatasını yakalayabilirsiniz. Seçimleriniz bunlar. Sorunuzu yanıtlamak için yanıtı güncelledi.
Aaron Hall

Cevabınız için teşekkürler, ama henüz tam olarak düşündüğüm şey değil. : Onaylama işlemi değerlendirilir: disable ideal olarak bağlam yöneticisi çeşit, çalışma zamanı sırasında bir işlev içinde iddia etmek istediğim foo()kapalı ve anahtarlama iddialar: with skip_assertion(): foo(). Bunun yararı, işleve başka bir bayrak eklemem
Matthijs

2
İşlevin bayt kodunu yeniden yazabilir, AST'yi yeniden yazabilir veya işlevin kendisini yeniden yazabilirsiniz. (her ikisi için manuel veya programlı olarak). AST'yi yeniden yazmak muhtemelen en güvenilir yaklaşım olacaktır ("basitçe" Assertnesneleri Passnesnelerle değiştirin ). Bir bağlam yöneticisi bunun için doğrudan çalışmaz, ancak bu şekilde dekore edilmiş işlevleri kullanan bir tür mekanizmaya sahip olabilirsiniz. Ne olursa olsun, tavsiye etmiyorum. Bunu yapmak istemenizin nedeninin kontrol etmediğiniz kodu aramanız ve AssertionErrors'ı almanız olduğundan şüpheleniyorum. Öyleyse muhtemelen farklı bir düzeltme bulmanız gerekir.
Aaron Hall

60

Python'u -O bayrağıyla çağırın:

test.py:

assert(False)
print 'Done'

Çıktı:

C:\temp\py>C:\Python26\python.exe test.py
Traceback (most recent call last):
  File "test.py", line 1, in <module>
    assert(False)
AssertionError

C:\temp\py>C:\Python26\python.exe -O test.py
Done

9
Assert bir işlev değildir, bu nedenle parenler gereksizdir.
Aaron Hall

15

Zaten verilen iki cevap Hem (biriyle Python çağrı geçerlidir -Oveya -OOkomut satırında).

İşte aralarındaki fark:

  • -OTemel optimizasyonları açın. Bu, derlenmiş (bayt kodu) dosyalar için dosya adı uzantısını .pyc'den .pyo'ya değiştirir.

  • -OOOptimizasyonlara ek olarak dokümanları atın -O.

( Python belgelerinden )



3

You should DEĞİL devre dışı (çoğu) iddialar. Dikkat başka yerde olduğunda, beklenmedik hataları yakalarlar. "On'un gücü" ndeki Kural 5'e bakın .

Bunun yerine, aşağıdaki gibi bazı pahalı iddia kontrollerini koruyun:

import logging
logger = logging.getLogger(__name__)

if logger.getEffectiveLevel() < logging.DEBUG:
    ok = check_expensive_property()
    assert ok, 'Run !'

Önemli iddiaları tutmanın ve assertifadelerin optimize edilmesine izin vermenin bir yolu, onları bir seçim ifadesi içinde yükseltmektir:

if foo_is_broken():
    raise AssertionError('Foo is broken!')

1
//, Sorun şu ki, ifade hala döngüsel karmaşıklığa katkıda bulunuyor ve hata işleme gerisini halledmeli?
Nathan Basanese

1
Yukarıdaki gibi korunacak iddialar, yürütmeyi önemli ölçüde yavaşlatan pahalı çağrılardır. Bazı algoritmalar için, bu tür kontroller, tüm programdan daha uzun büyüklük sıraları alabilir. Doğruluğu kontrol etmek için aynı algoritmanın saf ama daha basit bir uygulamasını (hata içermesi daha az olasıdır) çalıştırmayı düşünün. Veya normal çalışma için söz konusu olmayan bir şeyin ayrıntılı bir şekilde numaralandırılmasıyla yapılan bir kontrol.
Ioannis Filippidis

Okunabilirlikle ilgili pek bir sorun görmüyorum, çünkü böyle bir ifade koda iç içe geçme eklemiyor. Bunu bir işlev çağrısı olarak çıkarmak, eğer bir sorunsa, onu yoldan çıkarabilir (ve böyle bir yeniden düzenlemenin döngüsel karmaşıklığı azaltmasını bekliyorum). Her durumda, siklomatik karmaşıklık güvenlik kontrollerini yönetmemelidir.
Ioannis Filippidis

2

Optimize edilmiş modda çalıştırmak bunu yapmalıdır:

python -OO module.py
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.