티스토리 뷰



"파이썬 제어구조 1 - 파이썬 배우기(Python)"에 이은 글입니다. 파이썬의 흐름 제어를 다루는 기본적인 문장들을 다루고 있습니다. 



■ 주석문과 기타 제어문


프로그램이 커지고 복잡해지면 가독성이 떨어지게 마련인데 이를 보완해 줄 수 있는 방법 중의 하나가 코드에 주석을 달아 놓는 것입니다. 파이썬에서는 # 문자로 주석을 표시 합니다. 줄의 맨처음에 #를 표시하면 해당 줄은 모두가 주석이고 줄의 중간에 오면 그 이후가 모두 주석 입니다. 단, 따옴표 바깥에 표시해야 합니다.


    • 코딩 스키마 주석
      프로그램의 첫줄이나 두번째 줄에 기술하며, 코드의 인코딩을 기술 합니다. 코드중에 한글 인코딩(euc-kr)이 있을때는 다음과 같이 기술 합니다.
      # -*- coding: cp949 -*- 
      UTF-8 인코딩을 사용한다면 아래와 같이 기술합니다.
      #-*- coding:utf-8 -*-

    • 쉘 인터페이스
      리눅스/유닉스 환경에서 쉘로 하여금 어떤 파이썬 인터프리터를 사용할 것인지를 경로 지정으로 지시하는 방법 입니다.
      #!/usr/bin/env python 으로 사용할 수도 있고 #!/usr/bin/python 처럼 직접 경로를 지정할 수도 있습니다. 이렇게 쉘 인터페이스를 기록한 파이썬 코드는 사용자가 파일명만으로 프로그램을 실행시킬 수도 있습니다.

    • 여러줄에 걸친 문장 기술
      한 문장을 여러 줄에 걸쳐 기술할 때는 줄 맨 끝에 \를 입력하고 다음줄에 내용을 이어 갑니다.

    • 배열 및 사전의 원소 들은 \ 없이 여러줄에 걸쳐 입력할 수 있습니다.
      (), [], {}

    • 빈 줄에 대한 처리
      코드 블럭이 특정 문장에 내포된 상태로 여러 라인에 걸쳐 기술되고 있을 때 빈 줄은 해당 블럭의 끝을 표시하므로 하나의 블럭은 들여쓰기 상태에서 연속해서 기술해야 합니다.



■ 기본적인 입출력 및 코드 실행 문장


프로그램이 GUI환경인지, 웹 환경인지 아니면 단순 콘솔 환경인지에 따라 입출력 방법의 차이가 매우 큽니다. 본 포스팅에서는 학습이나 기타 디버깅의 용도로 간단하게 입출력하는 방법을 다루고자 합니다.


  • raw_input('메시지')
    표준 출력으로 '메시지'를 내보내고 표준 입력으로 부터 입력을 대기 합니다. 한줄을 입력받으면(엔터로 종료) 입력 받은 값을 스트링으로 리턴 합니다. 사용자가 숫자로 입력해도 리턴 값의 데이터 타입은 스트링 입니다. '메시지'는 생략할 수 있습니다. 아래의 예에서 123 숫자를 입력 했지만 타입은 'str' 임을 확인할 수 

    >>> type (raw_input('input???'))

    input???123

    <type 'str'>

  • input('메시지')
    raw_input과 동일하게 사용자 입력을 받지만, 입력 받은 스트링을 그대로 리턴하는 것이 아니라 입력 받은 내용을 파이썬 문장으로 처리한 결과를 리턴 합니다. 즉, 리턴 받은 문장에 대하여 eval(스트링)을 처리한 결과를 리턴 합니다. 결과적으로 사용자가 오류를 입력하면 프로그램에 심각한 영향을 줄 수도 있으므로 사용에 주의해야 합니다. 아래의 예를 보면 a+1 라는 입력이 단순 스트링이 아니라 변수 a를 참조하는 결과임을 확인할 수 있습니다.

    >>> a = 10

    >>> print input('input=')

    input=a+1

    11

  • print 표현,표현...
    표현으로 지정한 내용을 표준 출력으로 내보냅니다. print 한 문장을 한 줄에 출력하는데 문장 끝을 ,(comma)로 끝내면 다음 print 문장은 새로운 줄의 시작이 아니라 바로 옆으로 이어서 출력 합니다.

    >>>print "10/3 = ",

    >>>print 10/3

    10/3 = 3

    print는 기본적으로 표준 출력으로 내용을 출력하는데 표준 출력이 아닌 표준 에러(stderr)등으로 출력 방향을 바꿀때는(redirecting) 아래의 예와 같이 sys 모듈을 import한후 print >>sys.stderr, 표현, 표현...... 또는 print >>sys.stdout, 표현, 표현......으로 사용하면 됩니다. 아래의 그림은 인위적으로 stderr로 메시지를 보낸것과 표준 출력으로 보낸것을 비교한 결과 입니다.

    import sys

    print >>sys.stderr, "This is an error message"

    print "This is stdout"

    print >>sys.stdout, "This is also stdout"


  • eval('표현식')
    지정한 파이썬 표현식을 실행하고 그 결과를 리턴 합니다. 위에서 언급한 input()함수에서 사용자 입력후 수행하는 함수가 바로 eval()로 내부의 표현식은 대입식의 우측에 기술하는 식으로 한정하고 문법 오류가 없어야 합니다.

    >>> a = 10

    >>> eval (' a+ 5')

    15

  • exec('문장')
    eval은 지정한 식을 실행하고 그 결과를 리턴하지만, exec는 지정한 문장을 실행하는 것에 초점을 두고 있습니다. 즉, eval()에는 a= b+10과 같은 완전한 문장이나 print 문이 들어갈 수 없지만 exec는 여러줄의 문장도 가능하고 제한없이 문장들을 실행시킬 수 있습니다. 다만 값을 리턴하지는 않습니다.

  • compile('표현식 또는 문장', 파일명, 식의 종류)
    eval 또는 exec를 반복적으로 수행할 경우 해당 코드를 미리 컴파일하여 수행 속도를 높이기 위한 것으로 컴파일한 코드 오브젝트를 리턴하여 해당 오브젝트를 가지고 eval() 또는 exec문에 사용할 수 있습니다. 
    파일에서 코드를 불러오지 않는 경우에는 파일명에 '<string>'를 입력한다. 식의 종류는 그 내용에 따라 'eval' 이나 'exec'로 지정하면 되고 exec의 경우 한문장인 경우에는 'single'로 지정하면 됩니다.

    >>> a = compile ('10+1','<string>','eval')

    >>> print a

    <code object <module> at 01244188, file "<string>", line 1>

    >>> eval (a)

    11



■ 예외 처리(Exceptions)


예외는 정상적인 프로그램 흐름을 중단시키는 이벤트로 예외 상황이 발생하면 파이썬은 try 코드블럭에 해당하는 except 절을 찾고 해당하는 except절이 없으면 프로그램을 중단하고 메시지를 표준 에러(stderr)로 내보냅니다. 사용하기 위한 문법은 아래와 같습니다.


try:

코드블럭

except 예외코드, 예외오브젝트:

코드블럭

except (예외코드,예외코드):

코드블럭

except:

코드블럭

else:

코드블럭

finally:

코드블럭


except 다음에 예외코드나 오브젝트가 없으면 모든 예외를 처리하겠다는 구문 입니다. 예외오브젝트는 생략할 수 있고 기술되면 예외오브젝트가 전달 됩니다. 여러가지 예외를 한 코드블럭으로 처리할때는 튜플로 묶어서 전달 합니다. else절을 기술하면 예외가 발생하지 않은 경우에 처리 합니다. finally절을 기술하면 예외 발생 여부에 관계없이 try절 수행이후 수행합니다.

 

시스템에서 발생시킨 예외가 아니라 프로그램 수행도중 사용자가 예외를 인위적으로 발생시킬수 있는데 "raise 내장예외코드, 예외객체" 또는 "raise 클래스인스턴스, 예외객체"의 방식을 사용 합니다. 예외객체는 생략할 수 있으며 raise의 대상이 되는 클래스는 반드시 Exception 클래스를 상속 받아야하고 인스턴스 오브젝트를 raise문에 적용 합니다. except절에 사용할 예외코드로는 클래스명을 사용 합니다. 아래는 예외처리를 수행하는 Trac 코드의 일부입니다.


    try:
        import ctypes
        MOVEFILE_REPLACE_EXISTING = 0x1
        MOVEFILE_WRITE_THROUGH = 0x8
        MoveFileEx = ctypes.windll.kernel32.MoveFileExW

        def _rename(src, dst):
            if not isinstance(src, unicode):
                src = unicode(src, sys.getfilesystemencoding())
            if not isinstance(dst, unicode):
                dst = unicode(dst, sys.getfilesystemencoding())
            if _rename_atomic(src, dst):
                return True
            return MoveFileEx(src, dst, MOVEFILE_REPLACE_EXISTING
                                        | MOVEFILE_WRITE_THROUGH)

        CreateTransaction = ctypes.windll.ktmw32.CreateTransaction
        CommitTransaction = ctypes.windll.ktmw32.CommitTransaction
        MoveFileTransacted = ctypes.windll.kernel32.MoveFileTransactedW
        CloseHandle = ctypes.windll.kernel32.CloseHandle
        can_rename_open_file = True

        def _rename_atomic(src, dst):
            ta = CreateTransaction(None, 0, 0, 0, 0, 10000, 'Trac rename')
            if ta == -1:
                return False
            try:
                return (MoveFileTransacted(src, dst, None, None,
                                           MOVEFILE_REPLACE_EXISTING
                                           | MOVEFILE_WRITE_THROUGH, ta)
                        and CommitTransaction(ta))
            finally:
                CloseHandle(ta)
    except Exception:
        pass







댓글
댓글쓰기 폼