반응형

list boolean 판별 all, any

배경

Python의 가장 큰 매력은 있으면 편할 것 같은 내장함수가 많다는 것이다. 종종 여러요소들을 검사할 경우 검사 결과에 대해서 list에 담아서 확인을 하고 싶은 경우가 있다. 경우에 따라 모두 True이어야 하거나 하나라도 True 인 경우가 필요하다면, all()과 any() 내장 함수를 사용하면 된다.

사용 조건은 iterable (반복자 사용가능)으로 즉, 좀 더 쉽게 접근하자면 for in 문 사용이 가능한 list 같은 자료구조에 사용할 수 있다.

 

all()

입력받은 list 인스턴스중 모두다 True 이여야 True 값을 반환한다. 즉, 각 list내의 boolean 값이 각각 and 논리연산을 한 것과 같다.

a = [True, True, True]
b = [True, False, True]
all(a)
# True
all(b)
# False

 

any()

입력받은 list 인스턴스중 하나라도 True이면 True를 반환한다. 각 list내에 boolean 값이 각각 or 논리연산을 한 것과 같다.

a = [False, False, False]
b = [True, False, False]
any(a)
# False
any(b)
# True

 

 

반응형
반응형

datetime, timestamp, str 변환

배경

 어쩌다보니 플라스크를 이용해서 서버관련된 개발을 하게 되었다. 원래 도쿠 위키에 정리를 해놓은 문서이지만, 다시 블로그에 올리는게 나을 것 같아 정리를 한다.

 서버쪽에서 데이터를 수집 및 표시를 할 때 시간에 대해서 자주 다룬다. 특히 실시간으로 뭔가를 처리해야 할 경우나 데이터를 처리하는 경우 더 더욱 자주 사용한다. 참고로 하드웨어 쪽 펌웨어의 timestamp와 서버에서 말하는 timestamp 간 차이가 있으니 주의해서 이해를 해야 오해가 없다.

 

datetime 관리 팁

 서버에서 timestamp의 의미는 unix timestamp로 1초는 1의 값이 된다.

 

 파이썬에서는 내장모듈인 datetime을 중심으로 코드를 작성하는 것이 좀 더 단순한 구조가 된다. 이는 내장 모듈이기 때문에 어지간하면 ORM 모듈에서 지원을 하기 때문이다.

1. datetime now

from datetime import datetime

datetime.now()
# datetime instance now

 

2. datetime to timestamp

from datetime import datetime

timestamp = datetime.now().timestamp()

 

3. datetime to str

from datetime import datetime

datetimeStr = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%L")
# ex) 2021-06-07 14:57:01.113000

 

4. timestamp to datetime

from datetime import datetime

timestamp = datetime.now().timestamp()
dt = datetime.fromtimestamp(timestamp)

 

5. str to datetime

from datetime import datetime

datetimeStr = "2021-06-07 14:58:01.11100"
dt = datetime.strptime(datetimeStr, "%Y-%m-%d %H:%M:%S.%L")

 

참조 자료

(추후 추가)

반응형
반응형

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
반응형

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 공식 문서(영문)
국내 블로그 글

반응형
반응형

Python3 not의 코드 스타일

작성 계기

필자는 C/C++/C#을 주로 접한다음에 Python 을 접했기 때문에 해당 언어들은 관례상 not 연산자 !을 주로 앞에 쓰는 경우가 있다. 이유는 !는 눈에 비교적 잘 보이기 때문에 가독성을 위해서 그렇게 쓰는 버릇이 있기 때문이다. 하자만, 파이썬에서의 경우는 not 이라는 키워드를 직접 입력하기 때문에 C/C++/C#의 스타일과 다소 차이가 있다. 다만, 워낙 친인간적인 언어다 보니까 영문법과 같이 사용하는 것을 권장한다.

not의 코딩 스타일

다음은 코딩 스타일 비교이다. 결과적으로는 둘다 같은 결과를 얻을 수 있다.

전통적인 스타일

예시)

>>>tmpNum = 1
>>>not type(tmpNum) is str
True
>>>not type(tmpNum) is int
False

구글 코딩 스타일

예시)

>>>tmpNum = 1
>>>type(tmpNum) is not str
True
>>>type(tmpNum) is not int
False

어떤 방식이 좋은가?

두 예시에서 보듯이 결과적으로는 같기 때문에 사실은 상관이 없다. 하지만, 구글 코딩 스타일을 더 권장을 하는데, 이유는 앞에 괄호 없이 not이 있다보면, 가독상 사람입장에서는 (not type(tmpNum)) is str 으로 읽은 가능성이 있고, 경우에 따라서 잘못 의미를 해석할 수 있기 때문이다. 그밖에 성능상에서도 큰 차이는 없다.

반응형
반응형

Python3 : 삼항연산자(Ternary Operators)

작성한 계기

C를 먼저 익힌 개발자라면 3상연산자는 라인수는 적으면서 간단하게 조건문을 사용할 경우에 많이 사용한다. 다만, 파이썬에서는 전통적인 삼항연사자와 다르게 표현이 되어서 당황했었다. 그래서 기록으로 남긴다.

전통적인 삼항연산자

전통적으로 C/C++/C#과 같은 언어에서는 ? 기호를 삼항식으로 사용해왔다.

예시)

#include <stdio.h>

void TwoMultiple(const int num)
{
    printf("%d is %s\n", num, (num % 2 ? "even" : "odd"));
}

int main(const int argc, const char* argv[])
{
    TwoMultiple(1);
    // 1 is odd
    TwoMultiple(2);
    // 2 is even
    return 0;
}

화면 출력 코드가 길어서 코드가 길어지지만, 삼항식자체는 짧다.

파이썬의 삼항연산자

파이썬에서 삼항연산자는 처음부터 있던 것은 아니고 요구에 의해서 생기게 되었는데, 기존의 전통적인 방식과 많이 다르기에 많은 고심이 있던 것으로 생각된다. 간결한 기호를 사용하지 않고 기존의 if/else문을 한줄로 표현하는 방식을 사용하고 있다. if키워드 앞에 오는 값은 참(True)일때, else 다음에 오는 것은 거짓(False)일때 수행을 하게 된다. 그리고 if와 else 사이에는 조건문이 삽입되어 있는 구조이다.
예시)

def twoMultiple(num):
    resultStr = str(num) + ' is ' + ('odd' if num % 2 else 'even')
    print(resultStr)

twoMultiple(1)
# 1 is odd
twoMultiple(2)
# 2 is even

이전의 전통적인 삼항연산자보다는 좀 더 친 인간적인(?) 문법이 되었다. 그러나 대신 전통적인 삼항연산자 보다는 길어진 느낌이 있다. 또, 파이썬의 들여쓰기를 통한 scope를 구분한다는 효과와 함께 삼항연산자는 C/C++ 만큼 자주 사용하지 않을 것으로 보인다. 그리고 이 삼항연산자 패턴은 for문을 이용한 자료형 변경하는 패턴에서도 볼 수 있다.

삼항연산자를 보면서 느낀점

대부분의 프로그래밍 언어도 그렇지만, 활발하게 필요한 기능이 있다면 추가가 되고 있다. 다만 파이썬에서 전통적인 문법과 다른 것을 볼 때 마다 느끼는 것이 기능을 바로 추가 하지 않고 좀 더 나은 방법이 있는지 고민하면서 추가를 한다는 느낌을 받았다.

참조 자료

python 계단 밟기

반응형
반응형

Python3 타입검사(Type Check)

타입에 필자 생각

C/C++ 에서 주로 개발을 한 사람(필자의 경우) 입장에서는 자바스크립트나 파이썬처럼 변수(라고 쓰고 객체라고 읽고 쓰더라)의 형이 자유로운 경우 형이 바뀐 경우 문법상 문제가 없기 때문에 잘못된 변수 사용하는 것에 걱정을 한다. 그리고 결국 컴퓨터에서 동작하기 때문에 변수는 자유롭게 받는 것에 비해 타입 에러도 있다. 때문에 몇몇 유명한 개발자는 파이썬을 안좋게 본다. 그러나 이런 관점과 요구사항은 항상 개선책이 나오는 원동력이 되는 것 같다. 파이썬도 타입검사 메서드가 제공되면서 C++ 스타일의 코딩이 가능하기 때문이다.

type() vs isInstance()

입문자를 위한 서적에서는 대부분 type() 메서드를 잠시 소개했던 것으로 기억한다. 아마 isInstance()도 소개를 한다면, 시대가 많이 바뀌었거나 해당 입문서가 수준이 높다고 생각해야 한다.

type()

type() 메서드의 경우 입문서에서 소개한 것과 같이 파이썬에서 기본적으로 제공하는 자료형에 대해서 구분이 가능하다.

예시)

type(1) is int
# True
type([]) is list
# True
a = 1
b = 3
type(a) is type(b)
# True

그러나 이 type()의 한계는 class의 인스턴스의 경우 해당되는 클래스의 인스턴스인지만 확인을 한다. C++ 처럼 상속의 경우는 고려가 되지 않아서 상속받은 클래스의 인스턴스를 알아 볼 수 없다.

예시)

class Test1:
    pass
class Test2(Test1):
    pass

a = Test1()
b = Test2()
type(a) is Test1
# True
type(b) is Test2
# True
type(b) is Test1
# False

isInstance()

type()의 한계점을 해결해주는 것이 isInstance() 메서드이다. 개발자가 임으로 만든 class의 인스턴스의 특정 클래스인지 검사할 경우 자식 클래스의 인스턴스도 True로 리턴을 해준다. 때문에 개발자는 구현을 하면서 타입에 느슨한 연결을 구현을 좀 더 안전하게 할 수 있다.

예시)

class Test1:
    pass
class Test2(Test1):
    pass

a = Test1()
b = Test2()
isInstance(a, Test1)
# True
isInstance(b, Test2)
# True
isInstance(b, Test1)
# True

추가로 isInstance()는 튜플을 허용된다.

예시) unicode str 검사 방법 둘다 basestring 의 subclass임을 이용하는 방법

tmpStr = 'hello'
isInstance(tmpStr, (str, unicode))

무엇을 사용해야 하는가?

type()과 isInstance() 각각 특징이 있는 것이지 장단점이 있는 것이 아니기 때문에 적절히 활용하는 것이 좋다. 두 메서드를 적절히 사용하여 subclass를 확인 하는 방법도 있기 때문이다.

참조 자료

스택오브플러워

해시코드

반응형

+ Recent posts