프로그램을 짜다보면 데이터를 정렬해야하는 경우가 자주 있다. 간단한 데이터 구조에서는 쉽게 해결되지만 복잡한 구조일때는 어려움을 느낀다. 이럴때 파이썬이 제공하는 정렬관련 내용을 잘 알고 있으면 많은 개발 시간을 절약할 수 있다. 간단한 것 부터 살펴 보자
단순 리스트를 정렬하는 방법:
list의 sort() 메소드를 이용하면 된다. 실제 해당 리스트의 순서가 변경된다.
dect 사전을 정렬하는 방법:
sorted 함수를 이용한다. sorted는 파이썬 내장함수이다. 따라서, 별도 패키지 설치 없이 바로 이용할 수 있다. 사실 sorted 함수는 모든 형태의 정렬에 사용 할 수 있는 함수이다. (상기의 sort() 메소드는 리스트 객체에서만 이용가능하다) sorted()를 좀더 자세히 말하면 반복 가능한 객체를 입력 받아서 key 값에 따라 정렬하고 정렬된 리스트를 반환하는 함수이다. 아래와 같이 단순 리스트는 (value)값으로 정렬되고 사전은 key 값이 정렬된다.
그런데 사전의 정렬 결과를 보면 키만 정렬되어 반환한다. 원하는 것이 사전 그대로의 내용이 키 순서대로 정렬되기를 바라는 경우가 많이 있다. 이러한 경우에 lambda 함수를 이용해서 해결 할 수 있다. (lambda함수란 메모리 절약을 위해 임시성으로만든 함수로 이름 없는 함수로 생성-사용-소멸이 자동으로 이루어지는 함수이다. 어찌보면 간단하게 동작하는 함수로써 당연하고 불편한 부분은 제외한 함수이다. 자세한 내용은 다른 포스트에서...) 여기서 item은 반복가능한 객체 중 하나를 의미한다. 따라서 첫번째 객체로 (key1': 'value3') 이 된다. 아래 예시와 같이 item의 인덱스를 0으로하면 key를 기준으로 정렬되고 1로하면 value를 기준으로 정렬된다. 입력데이터와 동일한 사전 형식을 유지하기 위해 반환되는 값을 dict()를 이용하여 사전으로 변경해 준다.
<코드 출처: https://docs.python.org/3/howto/sorting.html> 그러나 이러한 방법의 단점은 데이터 구조의 변환 시 매우 주의해서 코드를 작성해야한다. 왜냐하면 6라인의 끝부분에 student[2] 처럼 상수(2)가 코드에 포함됨으로써 나이 앞에 새로운 항목 하나가 추가될 경우 동일한 작동을 위해서는 (3으로) 변경해 주어야 한다.
리스트 안에 들어있는 사전을 정렬하는 방법
json 포맷을 사용할 경우 리스트 안에 사전이 들어있는 형태의 데이터 구조가 된다. 이런 형태의 정렬은 바로 위의 내용을 살짝 바꾸어서 사용가능하다. lambda 함수에서 받게되는 하나의 객체가 사전인 경우 이므로 keys() 메소드를 이용하면 된다. 아래 예시에서는 항목의 key가 하나이므로 .keys() 메소드를 통해 반환되는 값을 리스트로 바꾸고 첫번째[0]를 선택하면 모든 객체의 키값이 반환되게되고 이를 기준으로 정렬하게 된다.
그렇다면 value를 기준으로 정렬하려면 어떻게 해야할까??? 앞선 예제에서 처럼 0을 1로 바꾸면 되지 않을까? 라고 생각할 수 있지만 의미가 다르기 때문에 에러가 난다. 여기서의 0은 keys()로 반환받은 키값들 중에 첫번째([0])라는 의미 이기 때문에, 1로 바꿀 경우 두번째 키값이라는 의미가되고 이것을 찾으려하지만 첫번째 항목 데이터({'key1': 'value3'})에서 보다시피 key 값은 하나('key1')밖에 없기 때문에 에러가 발생한다. 따라서 key가 아니라 value를 기준으로 정렬하기 위해서 value를 나타내는 형식을 작성해야한다. 다소 복잡하지만 그 내용은 item[list(item.keys())[0]] 이다.
복잡한 구조에 대한 정렬이 필요한 경우 2
위의 '복잡한 구조에 대한 정렬이 필요한 경우' 에서 처럼 하면 위에서도 말했지만 단점이 있다. 데이터 구조에 따라 코딩 내용을 바꿔줘야 할 경우가 있다. 치명적일 수 있다. 그래서 아래의 내용 처럼 클래스로 만들어서 관리하면 데이터 구조의 추가 삭제에 따른 순서 걱정 없이 정렬을 할 수 있다.
Step 35/51:RUN apt-get install python3-venv ---> Running in2543cb338dd5 Reading package lists... Building dependency tree... Reading state information... The following additional packages will be installed: python3.6-venv The following NEW packages will be installed: python3-venv python3.6-venv 0 upgraded,2 newly installed,0 to remove and 9 not upgraded. Need to get7396Bof archives. After this operation,44.0 kB of additional disk space will be used. Do you want to continue?[Y/n] Abort. The command '/bin/sh -c apt-get install python3-venv' returned a non-zero code:1
원인:
이유는 설치도중 프롬프트가 뜨면서 추가 입력을 원하는데 도커 빌드 시에는 사람이 입력해줄 수 없기때문인다.
아래와 같이 옵션을 -y 를 주어 해결했다.
해결:
# Dockerfile RUN apt-get install -y python3-venv
현상:
pip 로 설치를 했는데 pip list 로 확인 시 설치 라이브러리가 안보임
원인:
우분투를 포함한 데비안 기반 플랫폼에서는 파이썬2가 기본으로 깔려있어서 파이썬 3를 쓰려면 pip 명령과 pip3 명령으로 잘 분리해야합니다.
추가 설치가 필요하다는 말이죠.
이와 같이 virtualenv도 설치가 필요한데 이미 파이썬3모듈에 하나로 포함되어있습니다.
따라서 아래의 명령을 실행하면 설치됩니다.
해결:
python3 -m venv env_dir_name
현상:
엄청나게 많은 도커 빌드를 시도하다 보면 갑자기 이전 빌드시 잘 진행했던 명령까지 가지도 못하고 갑자기 중간에 이상한 아래와 같은 메시지가 나올때가 있습니다.
그것도 apt-get update 하는데 말이죠…. 이런 경우 정말 당황스럽죠. 바꾼 것도 없는데 말이죠...
Step 3/49:RUN apt-get update ---> Running in38a9ded6a424 Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB] Get:2 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB] Err:1 http://security.ubuntu.com/ubuntu bionic-security InRelease At least one invalid signature was encountered. Err:2 http://archive.ubuntu.com/ubuntu bionic InRelease At least one invalid signature was encountered. Get:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB] Err:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease At least one invalid signature was encountered. Get:4 http://archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB] Err:4 http://archive.ubuntu.com/ubuntu bionic-backports InRelease At least one invalid signature was encountered. Reading package lists...W:GPG error: http://security.ubuntu.com/ubuntu bionic-security InRelease: At least one invalid signature was encountered.E: The repository 'http://security.ubuntu.com/ubuntu bionic-security InRelease' is not signed.W:GPG error: http://archive.ubuntu.com/ubuntu bionic InRelease: At least one invalid signature was encountered.E: The repository 'http://archive.ubuntu.com/ubuntu bionic InRelease' is not signed.W:GPG error: http://archive.ubuntu.com/ubuntu bionic-updates InRelease: At least one invalid signature was encountered.E: The repository 'http://archive.ubuntu.com/ubuntu bionic-updates InRelease' is not signed.W:GPG error: http://archive.ubuntu.com/ubuntu bionic-backports InRelease: At least one invalid signature was encountered.E: The repository 'http://archive.ubuntu.com/ubuntu bionic-backports InRelease' is not signed. The command '/bin/sh -c apt-get update' returned a non-zero code:100
원인:
이럴때 기존에 작업했다 실패했던 것들을 싹 정리해 줄 필요가 있어서 그런것 같습니다.
해결:
이런 걸 해결해주는 명령어가 있으니
바로 ~~~
docker image prune
그리고
docker container prune
입니다.
위 명령어로 정리해주고 나니까 다시 apt-get 설치는 잘 넘어가고
아까 에러가 발생했던 곳에서 에러가 발생하네요.. ㅠㅠ
현상:
가상환경 virtualenv가 생성안되는 경우
Step 26/49:RUN python3 -m venv $projectpath/prjenv ---> Running in e8efcf50027e The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. apt-get install python3-venv You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. Failing command:['/var/www/keywordsvc/prjenv/bin/python3','-Im','ensurepip','--upgrade','--default-pip'] The command '/bin/sh -c python3 -m venv $projectpath/prjenv' returned a non-zero code:1
원인:
정확지 않지만 apt-get 을 통해 파이썬 모듈을 설치하는 방법이 있으니 이를 이용하라는 것 같습니다.
해결:
제시한 명령어대로 "apt-get install python3-venv” 을 사용하여 해결
현상:
virtualenv 가상환경에 파이썬 패키지가 설치되지 않는 경우
혹은 시스템 전체에 패키지가 설치되는 경우
(두 경우 모두 만든 응용 프로그램에서 사용할 수 없어서 에러가 나는 경우입니다)
원인:
Dockerfile 은 shell script 와 다르기 때문에….
스크립트에서 처럼 순서대로 가상환경을 실행시키고 pip install 한다고 설치가되지 안습니다.
한 명령어 (RUN) 마다 하나의 process로 실행되어 명령어를 실행하기 때문에 다음의 명령어(RUN)에 영향을 주지 않습니다.
따라서 스크립트 처럼 순서대로 나열해놓고 도커를 빌드하면 빌드는 되지만 실제로 가상환경내에 원하는 패키지들이 설치되지 않습니다.
해결방법1 :
하나의 명령어(RUN)에서 “&&” 를 이용하여 가상환경의 실행과 명령어를 동시에 실행 시켜줍니다.
예를 들면 아래와 같습니다.
RUN . venv_dir/bin/activate && pip install numpy
해결방법2:
환경변수와 패스에 가상환경 경로를 잡아주는 방법입니다.
# in Dockerfile ENVVIRTUAL_ENV=/opt/venv RUN python3 -m venv $VIRTUAL_ENVENVPATH="$VIRTUAL_ENV/bin:$PATH"