เมื่อคุณต้องการลองทำข้อยกเว้นโดยไม่ต้องจัดการข้อยกเว้นคุณจะทำอย่างไรใน Python
วิธีต่อไปนี้ถูกต้องหรือไม่
try:
shutil.rmtree(path)
except:
pass
เมื่อคุณต้องการลองทำข้อยกเว้นโดยไม่ต้องจัดการข้อยกเว้นคุณจะทำอย่างไรใน Python
วิธีต่อไปนี้ถูกต้องหรือไม่
try:
shutil.rmtree(path)
except:
pass
คำตอบ:
try:
doSomething()
except:
pass
หรือ
try:
doSomething()
except Exception:
pass
ความแตกต่างคือว่าครั้งแรกที่หนึ่งจะจับKeyboardInterrupt
, SystemExit
และสิ่งที่ชอบที่จะได้มาโดยตรงจากไม่exceptions.BaseException
exceptions.Exception
ดูเอกสารประกอบสำหรับรายละเอียด:
try: shuti.rmtree(...) except: pass
จะระงับข้อผิดพลาดใด ๆ อย่างไม่หยุดยั้ง (แม้ว่าคุณจะสะกดผิดshutil
ทำให้ a NameError
) - อย่างน้อยที่สุดก็ทำได้except OSError:
โดยทั่วไปถือว่าเป็นแนวปฏิบัติที่ดีที่สุดในการตรวจจับข้อผิดพลาดที่คุณสนใจในกรณีที่shutil.rmtree
เป็นไปได้OSError
:
>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
[...]
OSError: [Errno 2] No such file or directory: '/fake/dir'
หากคุณต้องการเพิกเฉยต่อข้อผิดพลาดนั้นคุณจะทำ:
try:
shutil.rmtree(path)
except OSError:
pass
ทำไม? สมมติว่าคุณผ่านฟังก์ชันจำนวนเต็มแทนสตริงโดยไม่ตั้งใจ
shutil.rmtree(2)
มันจะให้ข้อผิดพลาด"TypeError: บังคับให้ Unicode: ต้องการสตริงหรือบัฟเฟอร์พบ int" - คุณอาจไม่ต้องการที่จะเพิกเฉยซึ่งอาจเป็นการยากที่จะแก้ปัญหา
หากคุณแน่นอนต้องการที่จะไม่สนใจข้อผิดพลาดทั้งหมดจับException
มากกว่าเปลือยexcept:
คำสั่ง อีกครั้งทำไม
การไม่ระบุข้อยกเว้นจะดึงดูดทุกข้อยกเว้นรวมถึงSystemExit
ข้อยกเว้นที่ตัวอย่างเช่นsys.exit()
ใช้:
>>> try:
... sys.exit(1)
... except:
... pass
...
>>>
เปรียบเทียบสิ่งต่อไปนี้ซึ่งออกอย่างถูกต้อง:
>>> try:
... sys.exit(1)
... except Exception:
... pass
...
shell:~$
หากคุณต้องการเขียนโค้ดให้ทำงานได้ดีขึ้นOSError
ข้อยกเว้นสามารถแสดงถึงข้อผิดพลาดต่าง ๆ ได้ แต่ในตัวอย่างข้างต้นเราเพียง แต่ต้องการละเว้นErrno 2
ดังนั้นเราจึงอาจมีความเฉพาะเจาะจงมากขึ้น:
import errno
try:
shutil.rmtree(path)
except OSError as e:
if e.errno != errno.ENOENT:
# ignore "No such file or directory", but re-raise other errors
raise
shutil.rmtree
ไม่ได้เป็นตัวอย่างที่ดีที่สุดเพราะคุณก็จะใช้ignore_errors=True
สำหรับการทำงานว่า ..
เมื่อคุณเพียงแค่ต้องการลองจับโดยไม่ต้องจัดการข้อยกเว้นคุณจะทำอย่างไรใน Python?
ขึ้นอยู่กับสิ่งที่คุณหมายถึงโดย "จัดการ"
หากคุณต้องการจับโดยไม่ต้องดำเนินการใด ๆ รหัสที่คุณโพสต์จะใช้งานได้
หากคุณหมายความว่าคุณต้องการดำเนินการกับข้อยกเว้นโดยไม่หยุดข้อยกเว้นจากการขึ้นสแต็กคุณก็ต้องการสิ่งนี้:
try:
do_something()
except:
handle_exception()
raise #re-raise the exact same exception that was thrown
ก่อนอื่นฉันขออ้างอิงคำตอบของ Jack o'Connor จากกระทู้นี้ กระทู้ที่อ้างอิงได้ปิดดังนั้นฉันเขียนที่นี่:
"มีวิธีใหม่ในการทำสิ่งนี้ใน Python 3.4:
from contextlib import suppress
with suppress(Exception):
# your code
นี่คือความมุ่งมั่นที่เพิ่มเข้ามา: http://hg.python.org/cpython/rev/406b47c64480
และนี่คือผู้เขียน Raymond Hettinger พูดถึงเรื่องนี้และทุกประเภทของ Python hotness อื่น ๆ : https://youtu.be/OSGv2VnC0go?t=43m23s
สิ่งที่เพิ่มเข้ามาของฉันคือ Python 2.7 ที่เทียบเท่า:
from contextlib import contextmanager
@contextmanager
def ignored(*exceptions):
try:
yield
except exceptions:
pass
จากนั้นคุณใช้เหมือนใน Python 3.4:
with ignored(Exception):
# your code
เพื่อความสมบูรณ์:
>>> def divide(x, y):
... try:
... result = x / y
... except ZeroDivisionError:
... print("division by zero!")
... else:
... print("result is", result)
... finally:
... print("executing finally clause")
โปรดทราบว่าคุณสามารถดักจับข้อยกเว้นดังนี้:
>>> try:
... this_fails()
... except ZeroDivisionError as err:
... print("Handling run-time error:", err)
... และยกข้อยกเว้นเช่นนี้อีกครั้ง:
>>> try:
... raise NameError('HiThere')
... except NameError:
... print('An exception flew by!')
... raise
วิธีการละเว้นข้อยกเว้นอย่างถูกต้อง?
มีหลายวิธีในการทำเช่นนี้
อย่างไรก็ตามตัวเลือกตัวอย่างมีวิธีแก้ไขปัญหาอย่างง่ายที่ไม่ครอบคลุมกรณีทั่วไป
แทน
try:
shutil.rmtree(path)
except:
pass
ทำเช่นนี้:
shutil.rmtree(path, ignore_errors=True)
shutil.rmtree
นี้เป็นเฉพาะอาร์กิวเมนต์ คุณสามารถดูความช่วยเหลือได้โดยทำสิ่งต่อไปนี้และคุณจะเห็นว่าสามารถช่วยให้เกิดข้อผิดพลาดได้เช่นกัน
>>> import shutil
>>> help(shutil.rmtree)
เนื่องจากสิ่งนี้ครอบคลุมเฉพาะกรณีตัวอย่างแคบ ๆ ฉันจะแสดงให้เห็นถึงวิธีการจัดการสิ่งนี้หากไม่มีข้อโต้แย้งคำหลักเหล่านั้น
เนื่องจากด้านบนครอบคลุมเฉพาะกรณีตัวอย่างแคบ ๆ ฉันจะแสดงให้เห็นถึงวิธีการจัดการต่อไปหากไม่มีข้อโต้แย้งคำหลักเหล่านั้น
คุณสามารถนำเข้าตัวsuppress
จัดการบริบท:
from contextlib import suppress
แต่จะระงับข้อยกเว้นเฉพาะที่สุดเท่านั้น:
with suppress(FileNotFoundError):
shutil.rmtree(path)
คุณจะไม่สนใจFileNotFoundError
:
>>> with suppress(FileNotFoundError):
... shutil.rmtree('bajkjbkdlsjfljsf')
...
>>>
จากเอกสาร :
เช่นเดียวกับกลไกอื่น ๆ ที่ระงับข้อยกเว้นได้อย่างสมบูรณ์ผู้จัดการบริบทนี้ควรใช้เพื่อครอบคลุมข้อผิดพลาดเฉพาะอย่างยิ่งซึ่งการดำเนินการโปรแกรมต่อไปอย่างเงียบ ๆ เป็นสิ่งที่ต้องทำ
โปรดทราบว่าsuppress
และFileNotFoundError
มีเฉพาะใน Python 3 เท่านั้น
หากคุณต้องการให้โค้ดทำงานใน Python 2 ด้วยโปรดดูหัวข้อถัดไป:
เมื่อคุณต้องการลอง / ยกเว้นโดยไม่ต้องจัดการข้อยกเว้นคุณจะทำอย่างไรใน Python
วิธีต่อไปนี้ถูกต้องหรือไม่
try : shutil.rmtree ( path ) except : pass
สำหรับโค้ดที่เข้ากันได้ของ Python 2 pass
เป็นวิธีที่ถูกต้องในการมีคำสั่งที่ไม่ใช้งาน แต่เมื่อคุณทำเปลือยexcept:
ที่เป็นเช่นเดียวกับการทำexcept BaseException:
ซึ่งรวมถึงGeneratorExit
, KeyboardInterrupt
และSystemExit
และโดยทั่วไปคุณไม่ต้องการที่จะจับสิ่งเหล่านั้น
ที่จริงแล้วคุณควรเจาะจงในการตั้งชื่อข้อยกเว้นเท่าที่จะทำได้
นี่คือส่วนหนึ่งของลำดับชั้นข้อยกเว้น Python (2) และอย่างที่คุณเห็นหากคุณมีข้อยกเว้นทั่วไปมากขึ้นคุณสามารถซ่อนปัญหาที่คุณไม่คาดหวัง:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StandardError
| +-- BufferError
| +-- ArithmeticError
| | +-- FloatingPointError
| | +-- OverflowError
| | +-- ZeroDivisionError
| +-- AssertionError
| +-- AttributeError
| +-- EnvironmentError
| | +-- IOError
| | +-- OSError
| | +-- WindowsError (Windows)
| | +-- VMSError (VMS)
| +-- EOFError
... and so on
คุณอาจต้องการจับ OSError ที่นี่และข้อยกเว้นที่คุณไม่สนใจคือถ้าไม่มีไดเรกทอรี
เราสามารถรับหมายเลขข้อผิดพลาดเฉพาะนั้นได้จากerrno
ห้องสมุดและรับอีกหากเราไม่มี:
import errno
try:
shutil.rmtree(path)
except OSError as error:
if error.errno == errno.ENOENT: # no such file or directory
pass
else: # we had an OSError we didn't expect, so reraise it
raise
หมายเหตุการเพิ่มเปล่าจะยกข้อยกเว้นดั้งเดิมซึ่งอาจเป็นสิ่งที่คุณต้องการในกรณีนี้ เขียนให้กระชับยิ่งขึ้นเนื่องจากเราไม่จำเป็นต้องpass
ใช้โค้ดในการจัดการข้อยกเว้นอย่างชัดเจน:
try:
shutil.rmtree(path)
except OSError as error:
if error.errno != errno.ENOENT: # no such file or directory
raise
เมื่อคุณเพียงแค่ต้องการลองจับโดยไม่ต้องจัดการข้อยกเว้นคุณจะทำอย่างไรใน Python?
วิธีนี้จะช่วยให้คุณพิมพ์ข้อยกเว้นคือ: (ลองใช้ catch โดยไม่ต้องจัดการข้อยกเว้นและพิมพ์ข้อยกเว้น)
import sys
try:
doSomething()
except:
print "Unexpected error:", sys.exc_info()[0]
try:
doSomething()
except Exception:
pass
else:
stuffDoneIf()
TryClauseSucceeds()
FYI ส่วนคำสั่งอื่นสามารถไปหลังจากข้อยกเว้นทั้งหมดและจะทำงานเฉพาะถ้ารหัสในการลองไม่ก่อให้เกิดข้อยกเว้น
else
ในบริบทนี้ และจะเพิ่มที่finally
จะเสมอทำงานหลังจากที่ใด ๆ (หรือไม่มีข้อยกเว้น)
ใน Python เราจัดการข้อยกเว้นที่คล้ายกับภาษาอื่น ๆ แต่ความแตกต่างคือความแตกต่างของไวยากรณ์ตัวอย่างเช่น
try:
#Your code in which exception can occur
except <here we can put in a particular exception name>:
# We can call that exception here also, like ZeroDivisionError()
# now your code
# We can put in a finally block also
finally:
# Your code...
shutil.rmtree(path, ignore_errors=True)
แต่สำหรับฟังก์ชั่นนี้เฉพาะคุณก็สามารถทำ อย่างไรก็ตามวิธีนี้ใช้ไม่ได้กับฟังก์ชั่นส่วนใหญ่