반응형

무선 디버그(wireless debug)

무선 디버그가 필요한 경우

일반적으로 안드로이드 개발을 할 경우 유선으로 연결된 상태에서 디버그를 진행을 한다. 하지만, OTG와 같이 다른 장비에 연결 상태에서 디버그를 진행해야 하는 경우에는 무선으로 디버그를 해야 한다.

ADB 디버그 툴

Android Studio에서는 무선 디버그 용도로 ADB를 활용할 수 있다. adb는 안드로이드 스튜디오를 설치할대 sdk가 설치된 폴더안의 platform-tools라는 폴더 안에 있다.

안드로이드 스튜디오에서 터미널 창을 연다음에 해당 경로로 이동한다.

만약 sdk 경로를 바꾼적이 없다면,윈도우즈 기준으로 아래의 경로로 접근하면 된다.

c:\user\[사용자 계정명]\AppData\Local\Android\sdk\platform-tools

형식의 경로에 있다.

필자의 경우

c:\user\hp\AppData\Local\Android\sdk\platform-tools

만약 경로를 바꾼적이 있는데 기억이 잘 나지 않는다면, tools -> sdk manager 로 창을 연다음에 android sdk 항목으로 보면 android sdk가 설치된 경로를 확인할 수 있다.

무선 환경 설정

다음 명령어로 유선에 연결된 안드로이드 장치를 확인할 수 있다.

adb devices

만약 아무것도 보이지 않는다면, 선을 다시 연결하고, 장치 접근이 허용이 되었는지 확인하자.

다음 명령어로 안드로이드 장치에서 디버그에 사용할 포트를 열어주자

adb tcpip [port]

필자의 경우는 다음과 같이 하였다.

adb tcpip 11000

다음 안드로이드 장치의 무선 ip 주소를 파악을 해야한다. 안드로이드 장치에서 직접 알아내는 방법이 있다. 하지만, adb에서는 안드로이드 장치가 연결된 상태에서는 shell로 접근이 가능하다.

adb shell

해당 shell 리눅스의 shell과 비슷한 방식이기 때문에 ifconfig 명령어로 무선 ip 주소(wlan0)를 파악 하면 된다.

$ifconfig
wlan0     Link encap:UNSPEC    Driver wcnss_wlan
          inet addr:192.xxx.xxx.xxx  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: xxxx::xxxx:xxxx:xxxx:xxxx/64 Scope: Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1896200 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1695900 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:889329097 TX bytes:459419469
~중략~
$exit

유닉스 계열 터미널과 같은 환경이다. 위의 wlan0(무선)의 inet addr이 있는 주소를 확인했으면, exit로 shell을 빠져나온다.

여기까지 마쳤다면, 이제 안드로이드 장치에 연결된 유선을 제거한 다음에 adb를 연결을 하면 된다.

adb connect [ip]:[port]

필자의 경우

adb connect 192.168.1.136:11000

연결이 되면, connected to 이하 메시지를 보여준다. 이제 이 상태에서 안드로이드 스튜디오에서 디버그를 실행하면, 마치 유선으로 연결된 것과 같이 똑같이 반응을 한다.

참조

회사 대표님의 조언

반응형

'Mobile Develop > (Android)JAVA' 카테고리의 다른 글

[Android]Magic Number와 String 관리  (0) 2020.02.12
반응형

Basic class 문법

Java와 관계

Java는 처음 등장시 하나의 언어로 모든 플랫폼에서 동작한다는 철학으로 처음 큰 관심을 받았고, 현재는 가장 많은 개발자들이 현업에서 사용하고 있는 언어이다. 이러한 특징때문에 구글의 안드로이드는 Java를 개발지원 언어로 채택하여서 단기간에 ios 개발 생태계를 따라잡게 된다(인해전술로).

문제는 Java는 본래 임베디드(세탁기, 전자렌지 같은 것들)를 위해 설계된 언어였고, 썬마이크로즈를 오라클에서 인수하면서 오라클사의 소유이다. 때문에 Java 오라클과 구글간 분쟁이 있었고 오라클이 재판에서 승소를 하게 되었다. 하지만, 젯브레인즈(JetBrains)사에서 구글과 협력하여 kotlin(러시아 샹트페테부르크의 앞의 섬 이름)이 등장하게 된다.

안드로이드에서 Java를 대체하고자 하는 영향도 컸으며, 안드로이드에 특화된 언어라서 Java 코드를 kotlin으로 변환하는 것도 가능하다. 즉, 안드로이드 한정으로 Java로 된 것은 kotlin으로도 가능하다(아직 필자가 low수준까지 해보지 않아 확신 못하나 그렇게들 설명하고 있다).

class

코틀린(kotlin)은 안드로이드 한정으로 자바(Java) 대체 가능한 언어기 때문에 같은 개념인 클래스가 존재한다.

클래스의 상속

자바와 반대로 코틀린은 기본적으로 상속이 금지이다. 상속을 가능하게 하기 위해서는 open 키워드를 사용한다. 프로그래밍 언어에서 특정 키워드를 추가하여 허용을 한다는 것은 해당 동작에 대해서 보수적인 것을 뜻하기도 한다.

open class Animal {
    // contents
}

class Dog : Animal {
    // contents
}

인자를 받는 생성자가 있는 클래스를 상속하는 경우 초기화 상속도 가능하다.

open class Animal(val name : String) {
}

class Dog(name: String) : Animal(name) {
}

내부 클래스

클래스 내에서 클래스를 사용하는 경우 inner 라는 키워드를 앞에 붙여 줘야 한다. 이는 기존의 가독성 문제를 보완하기 위한 것으로 생각된다.

class OuterClass {
    var a = 10

    inner class OuterClass2 {
        fun someThing() {
            a = 20
        }
    }
}

추상 클래스

자바와 비슷하게. abstract 키워드를 사용한다.

abstract class A {
    abstract fun func()

    fun func2() {

    }
}

class B : A() {
    overide fun func() {
        println("hello")
    }
}

val b = B()

참고 자료

서적: 오준석의 안드로이드 생존코딩(코틀린편)

반응형
반응형

Magic Number와 String 관리

작성 계기

 처음부터 내가 작성한 앱은 아니지만, 문자열과 상수들이 Magic Number를 관리하는 클래스에 작성이 되어 있는 것을 보고 기겁을 하였다. 무엇보다 목록이 많은 프로젝트였는데, 그 많은 목록을 일일히 타이핑을 했다는 것에 대해서 대단하게 느껴졌다. 하지만, 고객사에서는 추후라도 해외 진출도 생각을 하고 있는 것으로 보이므로 힘들지만, Magic Number와 번역 가능성이 있는 것들을 분리하기로 했다.

그리고 하는김에 분리하는 기준에 대해서 작성하다 보니 일반적인 표준이 될 것 같기 때문에 정리하여 기록을 남긴다.

Magic Number

 Magic Number는 프로그램을 개발을 하다보면 상수로 자주 사용되는 값을 말한다. 특히 string 같은 문자열의 경우 ""를 사용해서 상수형 문자열의 내용이 같으나 자주 선언을 하게 되면, 선언한 횟수 만큼 메모리를 점유하게 된다(물론 최근에는 최적화 기술이 발달해서 알아서 최적화 해줄 가능성도 크다). 또한 해당 문자열이 유지보수 과정에서 수정되어야 하는 경우에는 수정해야 하는 문자열을 찾는 과정은 상당한 일이 된다.

 따라서 대부분 초급 이상의 개발자들은 이러한 Magic Number을 특별한 네임스페이스에 따로 관리를 한다. 그리고 프로그램 실행중에는 변하지 않지만 준 Magic Number에 해당이 되는 것은 Cofigure 같은 설정값을 들 수 있다. 이러한 값들도 특별한 네임스페이스에서 관리하는 것이 개발 후반으로 갈 수 록 정신건강에 좋다.

value/string 리소스

 공식 안드로이드 개발자 가이드라인에서는 다국어 지원 서비스를 원활하게 하기 위해서는 문자열을 res/value/string.xml 에 작성하기를 권장하고 있다. 그리고 다른 언어에 대해서는 한국어에 대해서는 res/value-ko/string.xml 형식으로 관리가 된다. 물론 프로젝트 관리 메뉴에서는 string 파일이 2개로 보인다. 또한 단순히 언어만 구분을 짓는 것이 아니라 기기, 화면 비율 등에 따라서 문자열을 다르게 조절할 수 있다(자세한 것은 공식 가이드라인을 참조)

Magic Number와 value/string 리소스 구분 기준

 로직을 구현하는 문자열의 경우에는 언어에 상관이 없는 문자열들은 코드상 Magic Number로 간주하고 관리하는 것이 좋다(모드, 기능명, 분기 같은 문자열은 Magic Number로 간주).

 JAVA에서는 switch문에서 문자열로 구분을 할 수 있는 기능들이 있다. 이 switch문에서 case로 입력 받는 값은 상수형이어야 한다. 그러나 리소스에서 가져온 문자열은 일반 문자열이기 때문에 바로 swith문의 분기로 사용할 수 없다. 당연한 이야기지만, 언어가 바뀌면, 기준도 바뀌는 위험이 있기 때문이다.

덤, error: unescaped apostrophe in string 에러

종종 string.xml 에 "'"가 있는 경우에 발생하는 에러이다. 해당 문자열을 ""으로 감싸주거나, ' 앞에 \을 붙여주면 된다.

반응형

'Mobile Develop > (Android)JAVA' 카테고리의 다른 글

[Android Studio]무선 디버그(wireless debug)  (0) 2020.03.25
반응형

final 키워드

작성 계기

근래에 안드로이드 개발을 단기로 하게 되면서 전세계에서는 많이 사용하지만, 내 입장에서는 실무 개발을 해본적이 없는 JAVA로 개발을 해야 했기 때문에 기초적이지만, 기록으로 남긴다.

final의 기본 개념

final 변수

  • 한번만 초기화가 가능함.
    C/C++ 에서는 const 키워드와 성격이 거의 비슷하나 사용 방식은 차이가 있음.

    final 메서드

  • 해당 메서드를 Overide를 하거나 숨길 수 없음.
    아직 JAVA 경험이 많이 없어서 일 수 있으나, 실제로 사용된 코드를 본적은 없음

    final 클래스

  • 더 이상 상속이 불가능함.
    대표적인 사례로 java.lang.System, java.lang.String 등 있다(C++의 경우 String을 상속받아서 확장해서 사용하는 경우가 많음.)

final을 써야 하는 예시

magic number(상수)

어떤 소프트웨어를 개발을 해도 쉽게 직면하는 고민이다. 코드 유지보수와 높은 성능의 소프트웨어가 되기 위해서 magic number를 적절한 혹은 특정 namespzce 에 넣을 때 static과 함께 사용된다.

public class ConstVal {
    final static int powerCode = 0xFF;
    ...
}

익명 클래스

익명 클래스에서 변수를 참조할 때, 자신을 생성한 지역 클래스의 변수를 참조할 경우 사용. 이는 익명 클래스의 인스턴스가 살아 있으나 해당 인스턴스가 참조한 변수가 메모리상 없어지는 것을 방지하기 위해서 정해진 규칙이라 한다.

대부분은 지역 클래스라는 용어를 사용하다 보니 이해를 바로 못 하는 경우가 많은 듯 하다. 실제로 익명 클래스가 인스턴스를 만드는 시점은 지역 클래스의 메서드내에서 코드 실행중에 생성이 된다.

문제는 메서드내의 임시로 선언하고 사용한 변수들은 메서드 실행이 종료가 되면, 후에 GC에 의해서 메모리상에서 제거가 되는데, 이 때 메서드 내에서 생성된 익명 클래스의 인스턴스는 그대로 유지가 된다. 이 때 만약 이 인스턴스가 메모리에서 제거된 변수를 참조하면, 문제가 발생할 수 밖에 없다. 이 때 final 키워드를 사용하면, 해당 변수는 별도로 저장을 하기 때문에 제거가 되지는 않는다고 한다.(람다식에서도 유효한지는 차후 조사해서 추가를 해야 할 듯함.)

참조자료

반응형
반응형

Multi-Progress 표시하기

작성 계기

이미지 유사도 검색 프로토타입 엔진을 만드는 과정에서 멀티 프로그래스를 사용하게 되었다. 문제는 검색을 하는 데이터가 많기 때문에 프로토타입 종료를 위한 테스트에 사용되는 데이터의 양이 많기 때문에 로드하는 데 생각보다 시간이 많이 걸린다.

문제는 설치 및 시연 시스템을 구축업무를 다른 사람이 어느정도 진행이 되고 있는지를 표시할 화면 필요하다. 그래서 찾던 중 스택오버플러우 형님의 코드를 확인하게 되었다. 문제는 원본 url을 메모를 안해서 잊어 버렸지만;;; 뭐 검색에 시간이 걸렸으니 다른 사람에게라도 도움이 되라고 기록으로 남긴다.

주의 사항

본래 curses 모듈은 유닉스 계열 터미널에서만 지원이 된다. 하지만, windows-curses 모듈을 pip로 설치를 하면, 해결이 된다. 모듈명 등 모든 것이 본래의 curses와 같아서 해당 모듈을 사용한 python 코드는 호환이 된다. 나중에는 내장 모듈로 이관되기를 희망한다.

>pip install windows-curses

예시 코드

import curses
import time

def report_progress(filename, progress):
    """progress: 0-10"""
    stdscr.addstr(0, 0, "Moving file: {0}".format(filename))
    stdscr.addstr(1, 0, "Total progress: [{1:10}] {0}%".format(progress * 10, "#" * progress))
    stdscr.refresh()

if __name__ == "__main__":
    stdscr = curses.initscr()
    curses.noecho()
    curses.cbreak()

    try:
        for i in range(10):
            report_progress("file_{0}.txt".format(i), i+1)
            time.sleep(0.5)
    finally:
        curses.echo()
        curses.nocbreak()
        curses.endwin()

참고 자료

반응형
반응형

임의의 progress status

작성 계기

tqdm 이라는 훌륭한 progress bar 렌더링 툴이 있지만, 구닥다리 환경에서 개발할 때 필요해서 약 10분정도 생각해서 임시로 만든 progress 상태를 표시해줌. 인터페이스는 대략 tqdm과 유사하게 작성을 하였고, 기본 generator 기능을 활용하여 구현하였음.

 

작성하고 보니 역시 프로그래밍 언어 부분의 발전은 개발자의 생산성 향상에 연결된다는 생각이 들었음.

예시

import time

def prog(jobs, desc=None):
    entire = len(jobs)
    progStr = "" if desc is None else desc
    progStr += " : [{} / {}]"
    for itN, itJob in enumerate(jobs):
        print(progStr.format(itN +1, entire), end="\r")
        yield itJob
    print()

if __name__ == "__main__":
    for it in prog(range(30), desc="잉여럭"):
        time.sleep(.5)
반응형

'Python > Python3' 카테고리의 다른 글

[python3]datetime, timestamp, str 변환  (0) 2021.06.07
[python3]Multi-Progress 표시하기  (0) 2019.12.23
[python3]깊은 폴더 생성(재귀호출)  (0) 2019.08.12
[Python3]selenium 모듈 에러 노트  (0) 2019.05.21
[python3]os.path 모듈  (0) 2019.05.04
반응형

깊은 폴더 생성(재귀호출)

작성 계기

은근히 자주 작성해서 기록으로 남김

코드

def checkAndMkdir(pathStr):
    """해당 경로가 없다면 폴더를 생성한다.
    파일이 포함된 경로도 상관 없음
    """
    _, ext = os.path.splitext(pathStr)
    startPath = pathStr if not ext else os.path.dirname(pathStr)
    if not os.path.exists(startPath):
        dirUpperedPath = os.path.dirname(startPath)
        if not os.path.exists(dirUpperedPath):
            checkAndMkdir(dirUpperedPath)
        os.mkdir(startPath)
반응형

'Python > Python3' 카테고리의 다른 글

[python3]Multi-Progress 표시하기  (0) 2019.12.23
[python3]임의의 progress status  (0) 2019.12.23
[Python3]selenium 모듈 에러 노트  (0) 2019.05.21
[python3]os.path 모듈  (0) 2019.05.04
[python3, code style]not의 코드 스타일  (0) 2019.04.30
반응형

OpenCV로 끊김이 적은 동영상 재생

코드

배경이야기가 너무 길어서 두괄식으로 본론인 코드를 먼저 기록한다.

import cv2
import time
import ipywidgets as widgets
import IPython.display as display
import copy

cap = cv2.VideoCapture(video_file)
wImg = widgets.Image(
    layout = widgets.Layout(border="solid")
)
display.display( wImg)

if cap.isOpened():
    ret, img = cap.read()
    while ret:
        # 동영상 파일에서 캡쳐된 이미지를 이미지 파일 스트림으로 다시 인코딩을 한다.
        tmpStream = cv2.imencode(".jpeg", img)[1].tostring()
        wImg.value = tmpStream
        # 20 프레임이 되기 위한 딜레이 다만, 실제로 입력한 것보다 조금 더 딜레이가 있다
        time.sleep(0.05)
        ret, img = cap.read()
cap.release()

배경(도입)

이직을 하고 딥러닝 관련 프로젝트를 하게 되면서 3년만에 IPython notebook을 사용하게 되었다. 지금은 통상 jupyter로 많이 불리기는 하지만, 여전히 IPython notebook의 흔적이 남아 있다. 암튼 jupyter에서는 OpenCV에서 기본적으로 제공하는 imshow()가 정상적으로 작동이 되지 않는다. 이는 초기 OpenCV가 python에서도 동작하게 지원을 할때 독특하게 자체 자료구조인 Mat를 사용하지 않고 numpy.ndarray 자료구조를 사용하게 되면서 IPython Notebook에서 자주 사용하는 matplotlib를 사용하면서 굳이 따로 지원할 필요성을 못 느껴서 그런 것 같다. 게다가 python에 전통적으로 사용하던 IPL 라이브러리 역시 numpy.ndarray구조를 이용하여 이미지 데이터를 관리 하기 때문에 호환도 비교적 쉽다.

OpenCV의 기초인 IO(입출력) 부분에서는 기본적으로 이미지를 화면에 띄우는 것과 동영상을 재생하는 것을 기본적인 과정이다. 이 과정에서 동영상은 여러장의 이미지를 갱신하면서 재생이 된다는 것을 원리로 배울 수 있다. 문제는 matplotlib 의 pyplot 모듈을 이용해서 이미지를 화면에 보여주는데, 이 모듈은 이름에서 볼 수 있듯이 원래는 그래프와 약간이 이미지를 처리하기 위한 모듈이다. 그러다 보니 로컬에서 사용하는 OpenCV에서 처럼 동일한 윈도우에 imshow() 메서드를 호출해서 이미지만 바꿔서 동영상이 재생되는 것을 보여줄 수 없다.

필자는 구글링을 했을 때 스택오버 플로워에서는 다양한 방법들을 제시된 것을 확인 했었는데, 크게 2가지 방법이 있었다. 첫번째 방법은 IPython Notebook에 html 태그 삽입하는 방식을 사용해서 작성하는 방법, 두번째 방법은 webGL 관련 모듈을 설치하여 해당 모듈에 연결하는 방법이다. 필자는 두번째 방법을 시도했었는데, 생각보다. 프래임 드랍이 심했다.

일반적으로 사람이 실시간으로 딜레이를 못느끼는 프래임은 약 20정도인 것을 과거 다른 프로젝트를 통해서 경험을 했었다. 당연히 20프레임 이하였으니 상당한 딜레이를 느꼈던 것이다. 한동안 실망하고 잊고 있었다.

그러던 우연히 ipywidgets 이라는 IPython 자체 지원 모듈중 Image 위젯을 사용해서 이미지를 보는 보조 툴을 만들 일이 있었는데, 생각보다 이미지 파일 전환에 딜레이가 적다는 생각이 들었다. Image 위잿의 파일의 바이너리 스트림을 입력하는 부분에 동영상에서 읽은 이미지를 인코딩을 해서 연속적으로 렌더링을 하게 하면 WebGL보다 부드럽게 이미지 재생이 되지 않을까? 하는 발상으로 테스트를 해보니 생각보다 20프레임 이상 재생이 되는 것을 확인 했었다.

여기서 추가로 테스트 할 점은 코덱을 jpeg 외에 png, bmp 각각 변경해서 시도를 해봤는데, 인코딩시 스트림의 크기 클 수로 느려지는 것을 확인했다. 즉 압축률이 좋을 수록 동영상 재생의 딜레이가 적어지는 것을 알 수 있었다.

반응형

'Python > Jupyter' 카테고리의 다른 글

WSL Ubuntu 22.04 jupyter notebook 실행 문제  (0) 2024.07.17
반응형

Python3 selenium 모듈 에러 노트

모듈 개요

일반적으로 웹 크롤링을 할 경우 JS를 활용하기 위해서 많이 사용된다. 관련 서적도 있기는 하다.

배경

약 300만개의 이미지가 프로젝트에서 필요해 간단하게 크롤링을 하면서 발견한 오류이다.

개발 환경

windows 10
python 3.6.8
vs code
chromedriver 74.xx

문제점

증상

살 사용하던 중 webdriver 인스턴스에서 호출되는 것은 문제가 안되는데, 메서드로 호출된 하위 element들이나 element 중에서 find_elements_by_class_name(), find_element_by_xpath(), find_elements_by_xpath() 같은 메서드를 호출하게 되면, 프로그램이 불안정하게 종료가 되어 버리는 현상이 발견되었다.

비정상적인 종료이기 때문에 chromedriver를 headless 옵션으로 실행할 경우 프로그램이 종료가 되어도 계속 프로세스가 유지 되는 현상도 있었다.

원인

execute_script()를 호출한 이후에 해당 증상이 나타난다. 전후 관계를 보았을때 selenium 모듈내의 버그로 생각된다. 에러메시지를 추적을 하면, errorNo 까지 호출은 하지만, 비정상적인 프로그램 종료가 되는 것을 보아 예외처리 부분도 아직 안된 것으로 보인다.

(임시) 해결 방법

오류를 신고를 해야 할 듯한다(귀찮다). execute_script() 실행과정에서 문제가 있고, 그 문제가 나중에 터지는 것으로 판단이 되기 때문에 일단은 webdriver 인스턴스를 refresh()를 호출하여 갱신 시킨후에 문제가 되는 메서드를 호출을 해봤다. 결과는 잘된다.문제는 중간에 이 과정으로 인해서 시간이 더 걸리게 된다.

반응형
반응형

Python3 os.path 모듈

작성하게 된 계기

C/C++ 개발자 출신 중 일부는 파일관리를 할 경우 바퀴의 재발명을 하는 경우가 많다. 물론 boost나 표준에 대해서 잘 알고 있다면 문제가 전혀 없다. 특히나 OS 크로스 플랫폼이 대세인 요즘에 OS에 따라서 (사실은 윈도우 때문에) file Path 표기법을 다르게 사용하는 문제는 어렵지는 않지만, 상당히 귀찮고 은근히 실수가 많은 분야이다. 그래서 요즘 대부분의 프로그래밍 언어들은 이러한 모듈 혹은 라이브러리를 제공을 하고 있다. 다만, 종종 이를 모르는 초보 및 현업에서 잠시 쉬신 분일 경우 모르는 경우가 있어서 기록을 남긴다. 다만, 여기는 자주 사용하는 내용만 적은 것이므로 자신이 익숙하다면 가능하면 레퍼런스를 보는 것이 좋다.

1. os.path 모듈 : 문자열 기반

내장 모듈로 경로를 다룰때 사용을 한다. 항상 파일관리 모듈을 만들경우 자주 사용하게 되는 것들을 아예 모아놓았다. 어쩌면, 경험적인 모듈이라고 볼 수 있다.

os.path.dirname

입력 받은 경로명에서 폴더(원래는 디렉토리가 표준이지만, 단어가 길어서 여기서는 편의상 폴더로 지칭함)만 출력을 해준다. 보통 파일 경로를 저장하고 있는 상태에서 폴더 경로만 알고 싶을때 많이 사용한다. 프로그램에서 파일을 관리하는 모듈을 작성할 경우 사용하기에 유용한 기능이다. 동작은 문자열 기반이다.

예시)

>>>import os
>>>os.path.dirname('/hello/world/tmp.txt')
'/hello/world'

os.path.isdir, os.path.isfile

입력 받은 경로명이 isdir의 경우 폴더이면, True이고 그외는 False를 반환하고 isfile의 경우 파일이면, True 그외는 False를 반환한다. 입력받은 문자열 기반으로 검사한다.

예시)

>>>import os
>>>os.path.isdir('C:\\hello\\world\\tmp.txt')
False
>>>os.path.isdir('C:\\hello\\world')
True
>>>os.path.isfile('C:\\hello\\world\\tmp.txt')
True
>>>os.path.isfile('C:\\hello\\world')
False

os.path.join

절대 경로와 상대경로를 조합할 경우 자주 사용하게 된다. 만약 자신이 만든 프로그램이 프로젝트 단위로 파일을 관리할 경우 프로젝트의 상위 폴더명에서 하위로 폴더를 새로 만들고 관리를 해 갈 경우에 매우 유용하다. 특이한 점은 첫 입력인자 이후 절대경로가 나오게 되면, 앞의 입력 인자로 인해 형성된 경로가 나중에 입력인자로 받은 절대경로로 초기화 되어버린다.

예시)

>>>import os
>>>os.path.join('C:\\hello\\home', 'world')
'C:\\hello\\home\\world'
>>>os.path.join('C:\\hello\\home', 'world', 'tmp.txt')
'C:\\hello\\home\\world\\tmp.txt'
>>>os.path.join('C:\\hello\\home', 'world', 'D:\\hello, 'tmp.txt')
'D:\\hello\\tmp.txt'

os.path.normcase

현재 운영체제에 맞게 경로 문자열을 정규화(Normalize)를 한다. 파이썬으로 다른 외부 모듈을 사용하다 보면 폴더의 구분자를 '/'로만 사용하는 경우가 있기 때문이다. 필자가 겪은 바로는 GUI 모듈에서 종종 그런 경우가 있다. 이 경우 해당 메서드를 사용하면 간단히 해결 된다. 대부분 윈도우 운영체제에서 사용하게 된다.

예시)

# 윈도우일 경우
>>>import os
>>>os.path.normcase('C:/hello/world')
'C:\\hello\\world'

os.path.split

내장 자료형인 str.split과 비슷하게 보이지만, 다르다. 입력받은 경로의 가장 뒷 부분에서 하나를 분리하여 2개의 string을 반환 한다. 작업중인 폴더에서 한 단계 상위 폴더 경로를 얻고 싶거나 파일경로에서 폴더 경로를 분리할 때 사용하면 유용하다.문자열 기반으로 동작을 한다.

예시)

>>>import os
# 유닉스 계열 운영체제의 경우(경로 표기가 간단해서 필자는 예시로 자주 들음)
>>>os.path.split('/hello/world/myhome')
('/hello/world', 'myhome')
>>>os.path.split('/hello/world/myhome.txt')
('/hello/world', 'myhome.txt')

# 폴더 표기를 잘못한 경우
>>>os.path.split('/hello/world/myhome/')
('/hello/world/myhome', '')

os.path.splitext

이름 그대로 확장자 부분을 분리하여 반환을 한다. 두번째 반환하는 인자가 확장자이다. 문자열 기반으로 작동을 한다. 때문에 확장자를 구분하는 .이 없을 경우에는 ''(빈)문자열를 반환한다.

예시)

>>>import os
>>>os.path.splitext('/hello/world/myhome.txt')
('/hello/world/myhome', '.txt')

# 확장자가 없는 경우
>>>os.path.splitext('/hello/world/myhome')
('/hello/world/myhome', '')

2. os.path 모듈 : 기능 기반

앞의 기능들은 대부분 문자열 기반이고 그외에 해당 경로의 파일 존재 여부나 파일 크기와 같은 것은

os.path.getctime, os.path.getmtime, os.path.getatime

윈도우에서 파일의 속성창을 열면 보이는 생성된 시각, 마지막 수정된 시각, 마지막 실행한 시각 순으로 값이 반환이 된다. 다만, os.path.getctime 의 경우 유닉스 계열 운영체제 중에서는 수정된 시각을 반환하는 경우가 있다. 반환된 시각의 단위는 초(sec) 이지만, 정수형이 아닌 실수로 표기한다.

파일 기본 속성은 파일을 열어야 알 수 있기 때문에 유닉스 계열의 경우 읽기 권한이 없는 경우 os.error를 발생 시킨다. 예외 처리를 잘 해주자.

os.path.getsize

입력인자로 받은 경로의 파일의 크기를 바이트로 반환을 해준다. 운영체제단에서 파일 크기를 알기위해서는 파일시스템에서 파일을 열어봐야 하므로 읽기 권한이 없으면, 파일을 열지 못하므로 os.error를 발생한다. 예외 처리를 잘 해주자.

참고자료

python3 공식 문서(영문)
국내 블로그 글

반응형

+ Recent posts