programing

파이썬에서 파일을 읽으려고 할 때 예외를 처리하는 좋은 방법은 무엇입니까?

bestprogram 2023. 7. 21. 21:46

파이썬에서 파일을 읽으려고 할 때 예외를 처리하는 좋은 방법은 무엇입니까?

파이썬으로 된 .csv 파일을 읽고 싶습니다.

  • 파일이 존재하는지 모르겠습니다.
  • 나의 현재 해결책은 아래와 같습니다.두 개의 분리된 예외 시험이 어색하게 병치되어 있어서 저는 엉성하게 느껴집니다.

더 예쁜 방법이 있을까요?

import csv    
fName = "aFile.csv"

try:
    with open(fName, 'r') as f:
        reader = csv.reader(f)
        for row in reader:
            pass #do stuff here
    
except IOError:
    print "Could not read file:", fName

이거 어때:

try:
    f = open(fname, 'rb')
except OSError:
    print "Could not open/read file:", fname
    sys.exit()

with f:
    reader = csv.reader(f)
    for row in reader:
        pass #do stuff here

다음은 읽기/쓰기 예제입니다.with 문은 예외 발생 여부에 관계없이 close() 문이 파일 개체에 의해 호출되도록 보장합니다.http://effbot.org/zone/python-with-statement.htm

import sys

fIn = 'symbolsIn.csv'
fOut = 'symbolsOut.csv'

try:
   with open(fIn, 'r') as f:
      file_content = f.read()
      print "read file " + fIn
   if not file_content:
      print "no data in file " + fIn
      file_content = "name,phone,address\n"
   with open(fOut, 'w') as dest:
      dest.write(file_content)
      print "wrote file " + fOut
except IOError as e:
   print "I/O error({0}): {1}".format(e.errno, e.strerror)
except: #handle other exceptions such as attribute errors
   print "Unexpected error:", sys.exc_info()[0]
print "done"

예외에 "else" 절을 추가하고 "with" 문을 "else" 섹션에 넣는 것은 어떻습니까?다음과 같이:

try:
  f = open(fname, 'rb')
except FileNotFoundError:
    print(f"File {fname} not found.  Aborting")
    sys.exit(1)
except OSError:
    print(f"OS error occurred trying to open {fname}")
    sys.exit(1)
except Exception as err:
    print(f"Unexpected error opening {fname} is",repr(err))
    sys.exit(1)  # or replace this with "raise" ?
else:
  with f:
    reader = csv.reader(f)
    for row in reader:
        pass #do stuff here

sys.exit() 대신 'raise'를 넣고 오류를 체인 위로 에스컬레이션할 수 있습니다.최상위 오류 처리기에서 오류에 대한 시스템 정보를 가져오는 것이 더 나을 수 있습니다.

Python 3에서 IOError는 OSError의 별칭입니다.확인하려면 코드를 실행합니다.

IOError is OSError
---
True

OSError는 파일 I/O 예외의 상위 클래스입니다.

      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
OSError.__subclasses__()
---
[ConnectionError,
 BlockingIOError,
 ChildProcessError,
 FileExistsError,
 FileNotFoundError,
 IsADirectoryError,
 NotADirectoryError,
 InterruptedError,
 PermissionError,
 ProcessLookupError,
 TimeoutError,
 io.UnsupportedOperation,
 signal.ItimerError,
 socket.herror,
 socket.gaierror,
 socket.timeout,
 ssl.SSLError,
 shutil.Error,
 shutil.SpecialFileError,
 shutil.ExecError,
 shutil.ReadError,
 urllib.error.URLError,
 gzip.BadGzipFile]

따라서 OS 오류를 파악하고 세부 정보가 필요한 경우 정확한 클래스를 확인합니다.

try:
    with open('hoge') as f:
        pass
except OSError as e:
    print(f"{type(e)}: {e}")
---
<class 'FileNotFoundError'>: [Errno 2] No such file or directory: 'hoge'

나는 팀 피에츠커 답변을 업데이트했는데, 왜냐하면 그것은 더 이상 유지되지 않는 파이썬 2를 사용하기 때문입니다.

저는 먼저 답변을 편집하려고 했지만, 편집 대기열이 꽉 차서 할 수 없었습니다.

import errno

fname = "no_such_a_file.txt"

try:
    f = open(fname, 'rb')
except OSError as e:
    if e.errno == errno.ENOENT:
        print(
            f"No such a file or directory (errno: { e.errno }):",
            fname, file=sys.stderr
        )
    else:
        # for other OS errno codes you may want to write
        # your more specific error messages which
        print(
            f"Cannot oppen file (errno: { e.errno } ):",
            fname,
            file=sys.stderr
        )
    sys.exit(os.EX_OSFILE)

with f:
    reader = csv.reader(f)
    for row in reader:
        pass #do stuff here

저는 또한 몇 가지 사소한 개선을 했습니다.

코드는 자체적으로 포함되어 있습니다.

오류 범위를 좁히는 데 도움이 되는 예외의 오류 번호를 확인해야 합니다.

다음에 오류를 기록하고 메시지를 기록해야 합니다.sys.stderr에가 아닌sys.stdout오류 메시지를 다른 파일로 리디렉션할 수 있기 때문입니다.

셸 스크립트와 같은 유닉스 환경에서 파이썬 코드를 사용하려면 0이 아닌 종료 코드(여기에 문서화되어 있음)를 반환해야 합니다.

#!/usr/bin/env bash
set -euo pipefail

if ./read_file.py 2> error.log
then
    echo "do stuff"
else
    exit_code=$?
    echo "file is not readable, exit code: $exit_code" > /dev/stderr
    exit $exit_code
fi
fname = 'filenotfound.txt'
try:
    f = open(fname, 'rb')
except FileNotFoundError:
    print("file {} does not exist".format(fname))

file filenotfound.txt does not exist

FileNotFoundError 예외 파일 또는 디렉터리가 요청되었지만 존재하지 않는 경우 발생합니다.errno ENONT에 해당합니다.

https://docs.python.org/3/library/exceptions.html
이 예외는 Python 2에는 없습니다.

@Josh의 예에 추가;

fName = [FILE TO OPEN]
if os.path.exists(fName):
    with open(fName, 'rb') as f:
        #add you code to handle the file contents here.
elif IOError:
    print "Unable to open file: "+str(fName)

이렇게 하면 파일을 열려고 시도할 수 있지만 파일이 없으면(IO 오류가 발생하는 경우) 사용자에게 경고합니다!

언급URL : https://stackoverflow.com/questions/5627425/what-is-a-good-way-to-handle-exceptions-when-trying-to-read-a-file-in-python