ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Chapter 06-5~06-6
    Do it! 점프 투 파이썬 2022. 6. 9. 01:04

    탭을 4개의 공백으로 바꾸기

    이번에는 문서 파일을 읽어서 그 문서 파일 안에 있는 탭(tab)을 공백(space) 4개로 바꾸어 주는 스크립트를 작성해 보자.

    • 필요한 기능은? 문서 파일 읽어 들이기, 문자열 변경하기
    • 입력받는 값은? 탭을 포함한 문서 파일
    • 출력하는 값은? 탭이 공백으로 수정된 문서 파일

     

    다음과 같은 형식으로 프로그램이 수행되도록 만들 것이다.

    python tabto4.py src dst

    tabto4.py는 우리가 작성해야 할 파이썬 프로그램 이름이고 src는 탭을 포함하고 있는 원본 파일 이름이다. dst는 파일 안의 탭을 공백 4개로 변환한 결과를 저장할 파일 이름이다.

     

    예를 들어 a.txt 파일에 있는 탭을 4개의 공백으로 바꾸어 b.txt 파일에 저장하고 싶다면 다음과 같이 수행해야 한다.

    python tabto4.py a.txt b.txt

     

    1. 우선 다음과 같이 tabto4.py 파일을 작성해 보자.

    # C:/doit/tabto4.py
    import sys

    src = sys.argv[1]
    dst = sys.argv[2]

    print(src)
    print(dst)

    sys.argv를 사용하여 입력값을 확인하도록 만든 코드이다.

     

    2. 다음과 같이 수행했을 때 입력값이 정상적으로 출력되는지 확인해 보자.

    C:\doit>python tabto4.py a.txt b.txt
    a.txt
    b.txt

    입력으로 전달한 a.txt와 b.txt가 정상적으로 출력되는 것을 확인할 수 있다.

     

    3. 테스트를 위한 원본 파일(탭을 포함하는 파일)인 a.txt를 다음과 같이 작성한다. 각 단어는 탭(\t)문자로 분리되도록 입력해야 한다.

    Life     is           too         short
    You    need    python

    입력으로 전달한 a.txt와 b.txt가 정상적으로 출력되는 것을 확인할 수 있다.

     

    4. 이제 탭 문자를 포함한 a.txt 파일을 읽어서 탭을 공백 4개로 변환할 수 있도록 코드를 변경해 보자.

    # C:/doit/tabto4.py
    import sys

    src = sys.argv[1]
    dst = sys.argv[2]

    f = open(src)

    tap_content = f.read( )
    f.close( )

    space_content = tab_content.replace("\t", " "*4
    print(space_content)

    위 코드는 src에 해당되는 입력 파일을 읽어서 그 내용을 tab_content라는 변수에 저장한 후 문자열의 replace 함수를 사용하여 탭(\t)을 4개의 공백으로 변경하는 코드이다.

     

    5. tabto4.py를 위와 같이 변경한 후 다음과 같은 명령을 수행해 보자.

    C:\doit>python tabto4.py a.txt b.txt
    Life    is    too    short
    You    need    python

    아마도 탭 문자가 공백 4개로 변경되어 출력될 것이다. 하지만 탭과 공백의 차이점을 눈으로 알 수는 없으므로 탭이 정상적으로 공백으로 변경되었는지 확인하기 어렵다.

     

    6. 이제 변경된 내용을 b.txt 파일에 저장할 수 있도록 다음과 같이 프로그램을 변경해 보자.

    # C:/doit/tabto4.py
    import sys

    src = sys.argv[1]
    dst = sys.argv[2]

    f = open(src)
    tab_content = f.read( )
    f.close( )
    space_content = tab_content.replace("\t", " "*4

    f = open(dst, 'w')
    f.write(space_content)
    f.close( )

    탭이 공백으로 변경된 space_content를 출력 파일인 dst에 쓰도록 코드를 수정하였다.

     

    7.프로그램을 실행하기 위해 다음 명령을 수행한다.

    C:\doit>python tabto4.py a.txt b.txt

    위 명령을 수행하면 b.txt 파일이 C:\doit 디렉터리에 생성된다. 에디터로 b.txt 파일을 열어서 탭이 4개의 공백 문자로 변경되었는지 확인해 보자. 프로그램을 작성할 때 사용하는 에디터는 대부분 탭과 공백 문자를 다르게 표시하므로 눈으로 확인이 가능할 것이다.

     

     

     

     

    하위 디렉터리 검색하기

    특정 디렉터리부터 시작해서 그 하위 모든 파일 중 파이썬 파일(*.py)만 출력해 주는 프로그램을 만들려면 어떻게 해야 할까?

     

    1. 다음과 같이 sub_dir_search.py 파일을 작성해 보자.

    # C:/doit/sub_dir_search.py

    def search(dirname):
        print(dirname)

    search("C:/"

    search 함수를 만들고 시작 디렉터리를 입력받도록 코드를 작성했다.

     

    2. 이제 이 디렉터리에 있는 파일을 검색할 수 있도록 소스를 변경해 보자.

    # C:/doit/sub_dir_search.py
    import os

    def search(dirname):
        filenames = os.listdir(dirname)
        for filename in filenames:
            full_filename = os.path.join(dirname, filename)
            print(full_filename)

    search("C:/")

    os.listdir를 사용하면 해당 디렉터리에 있는 파일들의 리스트를 구할 수 있다. 여기에서 구하는 파일 리스트는 파일 이름만 포함되어 있으므로 경로를 포함한 파일 이름을 구하기 위해서는 입력으로 받은 dirname을 앞에 덧붙여 주어야 한다. os 모듈에는 디렉터리와 파일 이름을 이어 주는 os.path.join 함수가 있으므로 이 함수를 사용하면 디렉터리를 포함한 전체 경로를 쉽게 구할 수 있다.

     

    위 코드를 수행하면 C:/ 디렉터리에 있는 파일이 다음과 비슷하게 출력될 것이다.

    [디렉터리 출력 예]

    C:/$Recycle.Bin
    C:/$WINDOWS.~BY
    C:/$Windows.~WS
    C:/adb
    C:/AMD
    C:/android
    C:/bootmgr
    C:/BOOTNXT
    ... 생략 ...

     

    3. 이제 C:/ 디렉터리에 있는 파일들 중 확장자가 .py인 파일만을 출력하도록 코드를 변경해 보자

    # C:/doit/sub_dir_search.py
    import os

    def search(dirname):
        filenames = os.listdir(dirname)
        for filename in filenames:
            full_filename = os.path.join(dirname, filename)
            ext = os.path.splitext(full_filename)[-1]
            if ext == '.py':
                print(full_filename)

    search("C:/")

    파일 이름에서 확장자만 추출하기 위해 os 모듈의 os.path.splitext 함수를 사용하였다. os.path.splitext는 파일 이름을 확장자를 기준으로 두 부분으로 나누어 준다. 따라서 os.path.splitext(full_filename)[-1]은 해당 파일의 확장자 이름이 된다. 위 코드는 확장자 이름이 .py인 경우만을 출력하도록 작성했다. C:/디렉터리에 파이썬 파일이 없다면 아무것도 출력되지 않을 것이다.

     

    4. 하지만 우리가 원하는 것은 C:/디렉터리 바로 밑에 있는 파일뿐만 아니라 그 하위 디렉터리(sub directory)를 포함한 모든 파이썬 파일을 검색하는 것이다. 하위 디렉터리도 검색이 가능하도록 다음과 같이 코드를 변경해야 한다.

    # C:/doit/sub_dir_search.py
    import os

    def search(dirname):
        try:
            filenames = os.listdir(dirname)
            for filename in filenames:
                full_filename = os.path.join(dirname, filename)
                if os.path.isdir(full_filename):
                    search(full_filename)
                else:
                    ext = os.path.splitext(full_filename)[-1]
                    if ext == '.py':
                        print(full_filename)
        except PermissionError:
            pass

    search("C:/")

    try ... except PermissionError로 함수 전체를 감싼 이유는 os.listdir를 수행할 때 권한이 없는 디렉터리에 접근하더라도 프로그램이 오류로 종료되지 않고 그냥 수행되도록 하기 위해서이다.

    full_filename이 디렉터리인지 파일인지 구별하기 위하여 os.path.isdir 함수를 사용하였고 디렉터리일 경우 해당 경로를 입력받아 다시 search 함수를 호출하였다. 이렇게 해당 디렉터리의 파일이 디렉터리일 경우 다시 search 함수를 호출해 나가면 (재귀 호출) 해당 디렉터리의 하위 파일을 다시 검색하기 시작하므로 결국 모든 파일들을 검색할 수 있게 된다.

     

    위 코드를 수행하면 C:/디렉터리에 있는 모든 파이썬 파일이 출력될 것이다.

     

     

    * 하위 디렉터리 검색을 쉽게 해주는 os.walk

    os.walk를 사용하면 위에서 작성한 코드를 보다 간편하게 만들 수 있다. os.walk는 시작 디렉터리부터 시작하여 그 하위 모든 디렉터리를 차례대로 방문하게 해주는 함수이다.

    import os

    for (path, dir, files) in os.walk("C:/"):
        for filename in files:
            ext = os.path.splitext(filename)[-1]
            if ext == '.py':
                print("$s/%s" % (path, filename))

    디렉터리와 파일을 검색하는 일반적인 경우라면 os.walk를 사용하는 것을 추천한다.

     

     

     

     

    출처 : "점프 투 파이썬"

Designed by Tistory.