2013년 10월 29일 화요일

Python programs

 이제까지 우리는 주로 대화형 mode 내에서 Python interpreter를 사용해왔다. 당신은 production에 사용할 Python program들이나 script들을 생성하기를 원할 것이다. 이 글에서는 command-line program들에 초점을 맞출 것이다. 만약 당신이 Linux/UNIX에 대한 경험을 가지고 있다면 command line에서 동작하는 script들에 친숙할 것이다. script들에는 정보를 전달하기 위해서 argument들과 option들을 줄 수 있고 입력과 출력을 redirect할 수도 있다. 만약 당신이 Windows만 사용했었다면 이와 같은 것들이 새롭게 느껴질 것이므로 더욱 이들의 가치에 대해서 흥미를 가져야 할 것이다.

 command-line script들이 GUI 환경에서 사용되는 것들보다 편리하지 않은 것은 사실이지만 Windows도 현재 강화된 command-line option들을 제공하고 있다는 것도 주목해야 한다. 이 글을 읽게 되면 매우 도움이 될 것이다. technique들이 매우 유용하며 code들을 실행하려면 알아두어야 할 지식이라는 것을 깨닫게 될 것이다. 특히 당신이 많은 수의 file들을 처리 시에 command-line technique을 매우 유용하게 사용할 수 있다.

 

매우 기초적인 program을 생성

 file 내에 연속적으로 배치된 Python 구문들의 어떤 group들도 program이나 script로 사용될 수 있지만 추가로 structure를 알아두면 표준화를 할 수 있으며 더 유용하게 사용할 수 있다. 다음 file은 가장 기본적인 형태로 file 내에서 단순하게 함수(function) 제어와 호출을 작성한 것이다.

 

File script1.py

def main():    # main 함수(function) 제어부
    print("this is our first test script file")
 
main()    # main 함수(function) 호출

 

  script에서 main은 유일한 제어 함수(controlling function)이다. 이 함수(function)은 첫 번째로 정의된 다음 호출되었다. 작은 program에서는 이런 것들에 있어서 많은 차이를 만들 수 없다고 하더라도, 위의 structure를 사용하는 것은 당신이 큰 application들을 만들 때 제어를 용이하게 해주며 더 많은 option들을 줄 수 있다. 그러므로 시작부터 이렇게 만들어 보는 습관은 좋은 idea라고 할 수 있다.

 

command line에서 script start

  당신이 Linux/UNIX를 사용한다면 path 상에 Python이 위치해야 하며 당신의 script와 동일한 directory 내에 있어야 한다. 그리고 command line에 다음 명령어를 입력하면 script start할 수 있다.

 

python3 script2.py

 

 이 글의 후반부에는 script들을 호출하는 다른 option들을 볼 것이지만 지금은 이 방식으로 진행할 것이다.

 

command-line argument

 다음 file에서 볼 수 있듯이 단순한 mechanism으로 command-line argument들을 전달할 수 있다.

 

File script2.py

import sys
 
def main():
    print("this is our second test script file")
    print(sys.argv)
 
main()

 

 command line에서 이를 다음과 같이 호출할 수 있다.

 

python3 script2.py arg1 arg2 3

 

 위 명령을 수행하면 다음 결과가 출력될 것이다.

 

this is our second test script file

['script2.py', 'arg1', 'arg2', '3']

 

 command-line argument들은 sys.argv에 문자열 list로 저장된 다는 것을 결과에서 볼 수 있다.

 

script의 입/출력을 redirect

 command-line option들을 사용하여 script의 입/출력을 redirect할 수 있다. 이를 볼 수 있도록 아래의 짧은 script를 사용할 것이다.

 

File replace.py

import sys
 
def main():
    contents = sys.stdin.read()    # stdin에서 contents로 읽어들인다.
    sys.stdout.write(contents.replace(sys.argv[1], sys.argv[2]))
    # 첫 번째 argument를 두 번째 argument로 대체한다.
 
main()

 

  script는 표준 입력을 read하여 첫 번째 argument와 일치되는 것들을 두 번째 argument로 변경하여 표준 출력으로 write한다. 다음 명령을 실행하면 infile에서 zero 0으로 변경한 복사본 outfile이 생성될 것이다.

 

python3 replace.py zero 0 < infile > outfile

 

 위 명령어는 UNIX 계열에서 동작한다는 것에 주의하라.

 

python script.py arg1 arg2 arg3 arg4 < infile > outfile

 

 위와 같은 형식의 명령은 infile을 입력 또는 sys.stdin 처리하여 outfile로 출력 또는 sys.stdout 처리하는 효과를 가진다. 이는 infile sys.stdin  'r' (read) mode 지정하고 outfile sys.stdout 'w' (write) mode로 지정한 것과 동일한 효과이다.

 

python3 replace.py a A < infile >> outfile

 

 위의 명령은 이전의 예제와는 다르게 출력 결과를 outfile에 겹쳐 쓰는 것이 아니라 덧붙인다.

 또한 pipe를 사용하여 하나의 명령어의 출력을 다른 명령어의 입력으로 보낼 수도 있다.

 

python3 replace.py 0 zero < infile | python3 replace.py 1 one > outfile

 

 위의 명령을 실행하면 infile에서 0 zero로 변경하고 1 one으로 변경한 내용이 outfile에 작성된다.

 

argparse module

 script command-line option들을 argument들처럼 받아들일 수 있도록 설정할 수 있다. argparse module option들과 argument들의 다른 type parsing할 수 있도록 지원을 제공하며 usage message들도 생성할 수 있다.

 argparse module을 사용하려면 ArgumentParser instance를 생성하여 option들을 지정한 후에 option들과 argument들을 모두 읽을 수 있도록 해줘야 한다. 다음 file argparse module의 사용례이다.

 

File args.py

from argparse import ArgumentParser
 
def main():
    parser = ArgumentParser()
    parser.add_argument("-f", "--file", dest="filename", help="write report to FILE",
                        metavar="FILE")
    parser.add_argument("-x", "--xray", dest="xray", help="specify xray strength factor")
    parser.add_argument("-q", "--quit", action="store_false", dest="verbose",
                        default=True, help="don't print status messages to stout")
    args = parser.parse_args()
 
    print("filename: {0}, xray: {1}, verbose: {2}"
            .format(args.filename, args.xray, args.verbose))
 
main()

 

 위의 script filename option ‘-f’ ‘--file’로 받으며 마지막으로 verbose option을 끌 수 있는 “quiet”를 기본값을 True로 지정하여 action=store_false로 지정하여 추가하였다.

 parse_args method argument 문자열을 object로 변환하여 namespace attribute들에 할당한 후에 namespace를 반환한다. 당신은 이들의 value dest parameter에 지정된 문자열을 key로 하여 얻을 수 있다.

 위의 script는 다음과 같이 실행시킬 수 있다.

 

python3 args.py -x100 -q -f infile

 

 다음과 같이 결과가 출력되는 것을 볼 수 있다.

 

filename: infile, xray: 100, verbose: False

 

 만약 유효하지 않은 option을 전달한다면 parse_args error를 발생시킬 것이다.

 

python3 args.py -x100 -r

 

 위의 명령을 실행하면 다음 결과값을 출력할 것이다.

 

usage: args.py [-h] [-f FILE] [-x XRAY] [-q]

args.py: error: unrecognized arguments: -r

 

fileinput module 사용

 script에서 fileinput module은 때때로 유용하게 사용될 수 있다. module은 하나 이상의 file들에서 입력 받은 line들의 처리를 지원한다. 자동으로 command line argument들을 읽어서 input file들의 list로 처리하여 file contents line들로 입력 받아서 연속적으로 iterate할 수 있게 해준다. module의 기본적인 사용 설명을 위해 아래의 script를 작성하였다. script ##으로 시작하는 line들을 제외한 line들을 출력한다.

 

File script4.py

import fileinput
 
def main():
    for line in fileinput.input():
        if not line.startswith('##'):
            print(line, end="")
 
main()

 

 이제 아래의 data file들을 작성해보자.

 

File sole1.txt

## sole1.txt: test data for the sole function
0 0 0
0 100 0
##
0 100 100

 

File sole2.txt

## sole2.txt: more test data for the sole function
12 15 0
##
100 100 0

 

python3 script4.py sole1.txt sole2.txt

 

 위의 명령어를 실행하면 다음과 같이 두 file에서 발췌된 data를 결합하여 결과값을 출력될 것이다.

 

0 0 0

0 100 0

0 100 100

12 15 0

100 100 0

 

 만약 command-line argument들을 주지 않는다면 표준 입력은 read된 모든 것이 된다. 만약 argument들 중에 하나가 hyphen(-)이면 표준 입력은 해당 지점에서 read 한다.

  module은 다수의 다른 함수(function)들도 제공한다. 이 함수(function)들은 특정 지점에서 read line들의 전체 개수 (lineno), 현재 file에서 읽어온 line들의 개수 (filelineno), 현재 file의 이름(filename), file에서 첫 line인지 여부(isfirstline), 표준 입력이 현재 read하고 있는지 여부 (isstdin)를 알려준다. 어떤 지점에서든 다음 file skip하거나 (nextfile) 전체 stream close (close)할 수 있다. 아래의 script는 입력 file들 내의 line들을 결합하고 file-start 구분자들을 추가하는 동작을 한다. script를 통해 위의 함수(function)들을 어떻게 사용하는지 설명하도록 하겠다.

 

File script5.py

import fileinput
 
def main():
    for line in fileinput.input():
        if fileinput.isfirstline():
            print("<start of file {0}>".format(fileinput.filename()))
        print(line, end="")
 
main()

 

 위의 script를 다음 명령으로 실행하면

 

python3 script5.py file1 file2

 

 다음과 같은 결과를 출력할 것이다. (점으로 표시된 line들은 원본 file 내의 line들을 나타낸다.)

 

<start of file file1>

...........................

...........................

<start of file file2>

...........................

...........................

 

 마지막으로 단일 filename argument filename들의 list fileinput.input을 호출하면 이들을 sys.argv argument들이 아닌 input file들로 사용한다. fileinput.input backup file을 생성한 후에 표준 출력이 input file에 기록되게 하도록 하는 inplace option도 가지고 있다. 이 마지막 option에 대한 설명은 documentation(http://docs.python.org/3.3/library/fileinput.html#fileinput.input)을 참조하라.

 

UNIX에서 바로 실행되도록 script를 작성.

 만약 UNIX 환경이라면 간단하게 바로 실행할 수 있는 script를 작성할 수 있다. script의 최상단에 다음 line을 추가하고 file을 적절한 mode로 변경한다. (ex. chmod +x replace.py)

 

#!/usr/bin/env python

 

 만약 Python 3이 기본 Python version이 아니라면 위의 line에서 python python3으로 바꿔줘야 Python 3 code로 인식을 한다.

 위의 설정을 한 후에 당신의 script path 상에 있는 위치에 놓아두면 (예를 들어, bin directory) 당신이 현재 위치한 directory에 상관없이 이 script name과 원하는 argument들을 입력하여 실행이 가능하다.

 

replace.py zero 0 < infile > outfile

 

 UNIX 상에서 bash shell을 사용하고 있다면 input/output redirection, command history, command 자동 완성을 지원한다.

 만약 당신이 UNIX 상에서 관리 script들을 작성한다면 group database 접근을 위한 grp, password database 접근을 위한 pwd, 자원 사용 정보 접근을 위한 resource, syslog 기능 동작을 위한 syslog, os.stat 호출로 취득되는 file 또는 directory에 대한 정보로 동작하는 stat과 같이 유용하게 사용할 수 있는 library module들이 많이 존재한다. Python Library Reference 내에서 이들의 정보를 찾아볼 수 있을 것이다.

 

 

program들과 module

 소수의 line으로 구성된 code를 포함하는 작은 script들에서 단일 함수(function)은 잘 동작될 것이다. 하지만 script가 이 수준을 넘게 되면 취할 수 있는 좋은 방법은 해당 code의 나머지 부분과 제어 함수(controlling function)을 분리하는 것이다. 여기에서는 이 technique과 몇몇 이점에 대해서 설명을 할 것이다. 일단 간단한 제어 함수(controlling function)을 사용하는 예제로 시작한다. 아래의 script 0 99 사이에 주어진 숫자에 대한 영어 이름을 반환한다.

 

File script7.py

#!/usr/bin/env python3
 
import sys
 
# 전환 mapping
_1to9dict = {'0': '', '1': 'one', '2': 'two', '3': 'three', '4': 'four',
             '5': 'five', '6': 'six', '7': 'seven', '8': 'eight',
             '9': 'nine'}
_10to19dict = {'0': 'ten', '1': 'eleven', '2': 'twelve', '3': 'thirteen',
               '4': 'fourteen', '5': 'fifteen', '6': 'sixteen',
               '7': 'seventeen', '8': 'eighteen', '9': 'nineteen'}
_20to90dict = {'2': 'twenty', '3': 'thirty', '4': 'forty', '5': 'fifty',
               '6': 'sixty', '7': 'senventy', '8': 'eighty', '9': 'ninety'}
 
def num2words(num_string):
    if num_string == '0':
        return 'zero'
    if len(num_string) > 2:
        return "Sorry can only handle 1 or 2 digit numbers"
 
    num_string = '0' + num_string    # 한 자릿수의 숫자 인 경우 왼쪽에 0을 추가
    tens, ones = num_string[-2], num_string[-1]
    if tens == '0':
        return _1to9dict[ones]
    elif tens == '1':
        return _10to19dict[ones]
    else:
        return _20to90dict[tens] + ' ' + _1to9dict[ones]
 
def main():
    print(num2words(sys.argv[1]))
 
main()

 

 다음 명령으로 위의 script를 실행하면

 

chmod +x script7.py

./script7.py 59

 

 아래의 결과를 출력할 것이다.

 

fifty nine

 

 제어 함수(controlling function) main은 적절한 argument num2words 함수(function)를 호출하여 결과를 출력한다. 아래쪽에 호출 part를 넣는 것이 표준이지만 가끔씩 file의 위쪽에 제어 함수(controlling function)의 정의를 하는 것도 볼 수 있을 것이다. 호출 part를 아래에 두면 호출 part를 본 후에 어떤 함수가 호출되는지 찾기 위해 다시 위로 scroll 하지 않아도 되므로 필자는 위의 예제처럼 호출 part를 아래에 두는 것을 선호한다. 또한 이 방식은 file의 나머지 부분에서 script 연결부를 깔끔하게 분리해준다. 이는 script들과 module들을 합칠 때 유용하다.

 사람들은 하나의 script 내에서 생성된 함수(function)들을 다른 module들이나 script들에서 사용할 수 있게 하려고 할 때 script들에 module들을 결합한다. 또한 module도 도구화되어 사용자들에게 quick interface를 제공하거나 자동화된 module testing을 위한 hook들을 제공하기 위한 script처럼 실행할 수 있다.

 제어 함수(controlling function) 주위에 다음 조건 test를 넣어서 script module을 결합한다.

 

if __name__ == '__main__':

    main()

else:

    # 필요하다면 module에 특화된 초기화 code를 여기에 작성한다.

 

 만약 해당 file script로 호출되면 name __main__으로 수행되고 제어 함수(controlling function) main이 호출된다. 만약 해당 file이 대화형 session이나 다른 module으로 import되었다면 name filename이 될 것이다.

 필자는 종종 시작할 때부터 script module과 같이 지정하여 작성한다. 이렇게 작성하면 session import하여 작성한 함수(function)들을 대화형으로 test하고 debug할 수 있게 해준다. 제어 함수(controlling function)은 외부에서 debug될 때만 필요하다. 만약 이 script가 확장되거나 다른 곳에 사용될 수 있도록 함수(function)들을 작성해야 한다면 이 함수(function)들을 module로 분리하거나 다른 module에서 이 module import 시키도록 할 수 있다.

 아래의 script script7.py module로 사용될 수 있게 설정하여 확장한 것이다. 기능도 숫자 0에서 99까지 항목을 허용하던 기존의 script에서 0에서 999999999999999까지 허용하도록 확장되었다. 제어 함수(controlling function) main은 이제 argument의 유효성을 검사하고 쉼표(,)도 제거하여 1,234,567 같이 사용자가 읽기 편한 입력도 허용한다.

 

File n2w.py

#!/usr/bin/env python3
"""n2w: number to words conversion module
: contains function num2words. Can also be run as a script
usage as a script: n2w num
                   (Convert a number to its English word description)
                   num: whole integer from 0 and 999,999,999,999,999(commas are
                   optional)
example: n2w 10,003,103
           for 10,003,103 say: ten million three thousand one hundred three
"""    # 예제를 포함하는 Usage message
 
import sys, string, argparse
 
# 변환 mapping
_1to9dict = {'0': '', '1': 'one', '2': 'two', '3': 'three', '4': 'four',
             '5': 'five', '6': 'six', '7': 'seven', '8': 'eight',
             '9': 'nine'}
_10to19dict = {'0': 'ten', '1': 'eleven', '2': 'twelve',
               '3': 'thirteen', '4': 'fourteen', '5': 'fifteen',
               '6': 'sixteen', '7': 'seventeen', '8': 'eighteen',
               '9': 'nineteen'}
_20to90dict = {'2': 'twenty', '3': 'thirty', '4': 'forty', '5': 'fifty',
               '6': 'sixty', '7': 'seventy', '8': 'eighty', '9': 'ninety'}
_magnitude_list = [(0, ''), (3, ' thousand '), (6, ' million '),
                   (9, ' billion '), (12, ' trillion '),(15, '')]
 
def num2words(num_string):
    """num2words(num_string): convert number to English words"""
    if num_string == '0':
    # 특수 조건(숫자 0)을 처리
        return 'zero'
 
    num_length = len(num_string)
    max_digits = _magnitude_list[-1][0]
 
    if num_length > max_digits:
    # 특수 조건(범위 초과 숫자)을 처리
        return "Sorry, can't handle numbers with more than " \
               "{0} digits".format(max_digits)
 
    num_string = '00' + num_string    # 왼쪽에 숫자를 붙임
    word_string = ''    # 숫자를 위한 문자열 초기화
 
    for mag, name in _magnitude_list:
    # 숫자를 포함하는 문자열 생성
        if mag >= num_length:
            return word_string
        else:
            hundreds, tens, ones = num_string[-mag-3], \
            num_string[-mag-2], num_string[-mag-1]
 
        if not (hundreds == tens == ones == '0'):
            word_string = _handle1to999(hundreds, tens, ones) + \
            name + word_string
 
def _handle1to999(hundreds, tens, ones):
    if hundreds == '0':
        return _handle1to99(tens, ones)
    else:
        return _1to9dict[hundreds] + ' hundred ' + _handle1to99(tens, ones)
 
def _handle1to99(tens, ones):
    if tens == '0':
        return _1to9dict[ones]
    elif tens == '1':
        return _10to19dict[ones]
    else:
        return _20to90dict[tens] + ' ' + _1to9dict[ones]
 
def test():
    """Function for module test mode"""
    values = sys.stdin.read().split()
 
    for val in values:
        num = val.replace(',', '')
 
        print("{0} = {1}".format(val, num2words(num)))
 
def main():
    parser = argparse.ArgumentParser()
 
    parser.add_argument("-t", "--test", dest="test",
                        action='store_true', default=False,
                        help="Test mode: reads from stdin")
 
    args = parser.parse_args()
 
    if args.test:
    # 만약 test 변수가 설정되면 test mode로 실행
        test()
    else:
        if len(args) < 1:
            parser.error("incorrect number of argments")
 
        num = sys.argv[1].replace(',', '')    # 숫자에서 쉼표(,)들을 제거
 
        try:
            result = num2words(num)
        except KeyError:
        # 숫자가 아닌 것들을 포함하는 argument로 인한 KeyError들을 잡아낸다
            parser.error('argument contains non-digits')
        else:
            print("For {0}, say: {1}".format(sys.argv[1], result))
 
if __name__ == '__main__':
    main()
else:
    print("n2w loaded as a module")

 

script로 위의 file을 호출하면 name __main__이 될 것이다. 만약 module import되면 name n2w이 될 것이다.

  script main 함수(function) command-line script로 실행될 때 실질적으로 단순화된 사용자 interface를 생성하기 위한 제어 함수(controlling function)의 목적을 잘 나타내고 있다. 이는 다음 작업들을 처리한다.

 

정확한 개수의 command-line argument들의 존재 여부를 검사하고 이들이 올바른 type인지 검사. 검사 결과에 부합하지 않는다면 사용자에게 사용예에 대한 정보를 알려준다. 이 부분에서는 argument가 하나인지 여부를 확인하지만 argument가 숫자로만 되어있는지는 명확하게 test하지 않는다.

특수 mode로 작동. 여기에서는 ‘--test’ argument가 있다면 test mode로 동작하게 해준다.

command-line argument들을 함수(function)들에서 요구되는 인수들과 mapping하여 적절한 방식으로 호출. 여기에서는 쉼표(,)들이 제거되며 단일 함수(function) num2words가 호출된다.

예상되는 exception들을 잡아내서 좀 더 사용자 친화적인 message로 출력.. 여기에서는 argument가 숫자가 아닌 것들을 포함할 때 발생할 수 있는 KeyError를 잡아낸다.

필요하다면 출력을 좀 더 사용자 친화적인 양식에 mapping. 여기에서 이것은 print 구문으로 실행된다.

 

 다음 file로 실행되는 test mode module num2words 함수(function)의 회귀 test 능력을 제공한다. 이 경우에는 file 내에 숫자들의 집합을 넣어서 사용한다.

 

File n2w.txt

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 98 99 100
101 102 900 901 999
999,999,999,999,999
1,000,000,000,000,000

 

 그리고 다음 명령을 입력한다.

 

python3 n2w.py --test < n2w.txt > n2w_out.txt

 

 출력 file은 쉽고 정확하게 check할 수 있다. 이는 수 차례 수행된다. 생성되는 동안에 그리고 num2words나 함수(function)들은 언제든지 반환될 수 있다.

 

이는 생성되는 동안에 수 차례 수행되며 값을 변경하기 위해 호출되는 num2words 또는 어떤 함수를 언제든지 반환할 수 있다. program을 실행하면서 철저히 전체 test를 해보는 것이 좋다. 1경 이상의 숫자는 이 program에서 처리할 수 없다.

 module test mode script command-line으로 사용할 때만 사용할 수 있는 함수(function)이다. 어느 회사는 개발 정책으로 언제나 Python으로 module을 개발하기도 한다. Python built-in data object type들과 method들은 일반적으로 개발을 더 쉽게 만들어 준다. 그리고 개발자들은 누구나 이 기법이 실질적으로 효과가 있다고 확신하고 있다. 추후에 Python code test하는 것에 대해서 더 상세하게 알아볼 것이다.

 여기에서 다른 option argument를 처리하는 main 함수(function) 부분 만 file로 분리하여 생성하고 이 file n2w import하는 것이다. 이렇게 하면 n2w.py main 함수(function) 내에는 test mode만 남게 될 것이다.

 

Python application을 배포

 당신의 script들을 source file(.py)들로 배포할 수 있다. 이들을 byte code(.pyc 또는 pyo file)로도 보낼 수 있다. byte code file portable하게 작성되었다면 어떤 platform 하에서도 작동될 것이다.

 

distutils

 distutils package 내에서 찾을 수 있으며 Python module들과 application들을 packaging하고 배포하는 표준 방식이다. 배포판을 생성하는 상세사항은 여기에서 다루지 않는다. 하지만 당신의 Python code packaging하고 배포하려고 한다면 python.org web site 상의 documentation distutils 사용에 대한 폭넓은 guide와 초보자 tutorial을 제공하므로 참조하기 바란다. distutils package에서 핵심은 당신이 작성하는 setup.py file이다. 이는 기본적으로 설치를 제어하는 Python program이다. distutils는 많은 수의 option들을 가지고 있으며 당신이 Windows와 몇몇 UNIX platform들에 맞는 배포판들을 생성할 수 있게 해준다.

 

py2exe 그리고 py2app

 이 글의 목적이 특정 platform 용도의 tool들을 다루는 것은 아니지만 py2exe Windows standalone program을 생성하고 py2app Mac OS X standalone program을 생성하는 것이라는 것은 알아두도록 한다. standalone program Python이 설치되지 않은 machine들 상에서도 단독으로 동작한다. 여러가지 측면에서 비춰볼 때 standalone 실행 program native Python application 보다 크고 유연성이 떨어지므로 이상적이지 않다. 하지만 몇몇 상황에서는 최선이 될 수도 있으며 가끔은 유일한 해결책이 될 수도 있다.

 

freeze를 통해 실행 가능한 program들을 생성

 Python이 설치되지 않은 machine들에서 동작할 수 있도록 freeze라는 tool을 통해 실행 가능한 Python program을 생성할 수도 있다. Python source directory에서 Tools subdirectory 내의 freeze directory 내에서 Readme file에서 사용설명서를 찾아볼 수 있을 것이다. freeze를 사용하려고 한다면 아마도 Python source distribution download 해야 할 것이다.

 Python program “freezing”하면 당신의 system에 설치된 C compiler를 사용하여 compile할 수 있도록 C file들을 생성한다. 실행 가능한 program들은 사용된 C compiler를 제공하는 platform에서만 동작할 것이다. 이 방식의 출력 결과에서 누군가가 당신의 Python code reverse-engineer할 수 있는 여지가 있다는 것에 주의하라. 이는 또한 언제나 간단한 방식으로 되지는 않는다. 당신이 C compiler를 사용하여 application을 생성하였다면 Python newsgroup에서 지원을 받아야 할 수도 있을 것이다. 하지만 대개 당신의 실행 가능한 program은 안정적으로 동작될 것이다.

 

요약

 가장 기본적인 형태의 Python script는 하나의 file 내에 Python 구문들의 순서열로 구성된다. line들로 된 Python code가 아니라 더 많은 line을 가지고 있는 script를 체계화하는 좀 더 구조화된 방식은 위에서 설명을 하였다. 제어 함수(control function)의 사용은 제어 logic interface logic의 간단한 방식으로 완충제 역할을 할 수 있다. module들은 script로 실행될 수 있도록 구조화 할 수 있으며 script들도 module들로 import될 수 있게 지정할 수 있다. 이는 큰 script들을 module화하여 생성할 수 있는 방식을 제공하고 module의 회귀 test mode의 수단으로 간단한 mechanism을 제공하기도 한다.

 script들은 UNIX 상에서 실행 가능한 file로 만들 수 있다. script들은 command-line에서 입/출력 redirection을 지원하도록 지정할 수 있으며 argparse module을 사용하여 command-line option들과 argument들의 복잡한 조합도 쉽게 parsing할 수 있게 할 수도 있다.

 Mac OS X에서는 script들을 다른 UNIX platform들과 동일한 방식으로 terminal window에서 실행할 수 있다. 추가적으로 Python program들을 개별적으로 실행하거나 Python file들을 여는 기본 application으로 Python Launcher를 사용할 수 있다.

 Windows에서는 double-click으로 열거나 window에서 실행하거나 command-prompt window를 사용하는 방식과 같이 다양한 방식으로 script를 호출할 수 있다. Windows 상에서 command-line option이나 argument들을 사용하고 redirection을 사용하는 것도 가능하지만 Linux/UNIX에서 만큼 편리하지는 않다. 그러므로 Windows 상에서 command-line argument들과 redirection test mode와 같이 특수한 경우에만 사용되는 것이 일반적이다. 세 가지 모든 platform들에서 GUI program들은 잘 실행된다.

 마지막으로 script의 대안으로 py2exe, py2app, freeze tool을 사용하면 Python interpreter를 설치하지 않은 machine에서도 실행 가능한 Python program을 만들 수 있다.

 이 글에서 script application을 생성하는 방법에 대한 이해를 했다면 다음으로는 Python으로 filesystem들과 상호작용하거나 조작하는 방법을 알아볼 것이다.