Practice/GTK+, Linux

'ps aux'와 'ps -ef'의 차이

ps -eps ax를 모든 프로세스를 보여준다는 의미에서 같다.


ps -fps u는 보여주는 필드를 정하는데 아래와 같은 소소한 차이가 있다.

ps -f
프로세스의 식별 정보를 더 잘 보여준다.

  • PPID : 부모 PID

ps u
프로세스의 상태 정보를 더 잘 보여준다.

  • %CPU : CPU 사용율
  • %MEM : 메모리 사용율
  • VSZ : 가상 메모리 크기
  • RSS : 실제 메모리 크기
  • STAT : 프로세스 상태


부모 프로세스와 자식 프로세스의 관계를 보려면 ps -ef
프로세스 상태를 보는 용도로는 ps aux가 더 적당하다.

Practice/Python, Perl

Ubuntu 16.04에서 Python 3.6 사용하기

Python 3.6 설치하기

Ubuntu 16.04에는 써드파티 PPA를 추가해야 python 3.6을 설치할 수 있다.

sudo add-apt-repository ppa:jonathonf/python-3.6

Python 3.6을 설치한다.

sudo apt-get update
sudo apt-get install python3.6


Python 3.6 설치 후 gnome-terminal 외 다수 프로그램이 동작하지 않는 문제 해결하기

Ubuntu 16.04의 몇몇 프로그램은 python 2.7, python 3.5 이외의 버전에서 동작을 보장하지 않는다.
이런 이유로 python 3.6 설치 이후로 문제가 발생하는 프로그램이 나타날 수 있다.(대표적으로 gnome-terminal)
시스템이 사용하는 python 버전을 2.7이나 3.5로 지정해야 한다.

간단한 방법

사용할 python을 등록한다.

sudo rm /usr/bin/python
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.5 2
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.6 3

아래 명령으로 python2.7을 선택한다.

sudo update-alternatives --config python
There are 2 choices for the alternative python (providing /usr/bin/python).

  Selection    Path                Priority   Status
------------------------------------------------------------
  0            /usr/bin/python2.7   1         auto mode
* 1            /usr/bin/python2.7   1         manual mode
  2            /usr/bin/python3.5   2         manual mode
  3            /usr/bin/python3.6   3         manual mode

Press <enter> to keep the current choice[*], or type selection number:

python 버전 2, 3을 분리하여 해결하는 방법

python2와 python3을 각각 등록한다.

python2를 등록은 아래 명령어면 충분하다.

sudo rm /usr/bin/python2
sudo update-alternatives --install /usr/bin/python2 python2 /usr/bin/python2.7 1

python3를 등록은 아래 명령어로 등록하고 사용할 버전을 고르면 된다.

sudo rm /usr/bin/python3
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.5 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 2

아래 명령으로 원하는 버전을 선택한다.

sudo update-alternatives --config python3

python3는 목록 중에 원하는 것을 아무거나 선택해도 무방하다.

There are 2 choices for the alternative python3 (providing /usr/bin/python3).

  Selection    Path                Priority   Status
------------------------------------------------------------
  0            /usr/bin/python3.5   1         auto mode
* 1            /usr/bin/python3.5   1         manual mode
  2            /usr/bin/python3.6   2         manual mode

Press <enter> to keep the current choice[*], or type selection number:

이제 시스템의 기본 python의 환경을 구성한다.
과정은 python3 선택 과정과 유사하다.

sudo rm /usr/bin/python
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 2

시스템의 기본으로 python2를 선택한다.

sudo update-alternatives --config python
There are 2 choices for the alternative python3 (providing /usr/bin/python).

  Selection    Path                Priority   Status
------------------------------------------------------------
  0            /usr/bin/python2     1         auto mode
* 1            /usr/bin/python2     1         manual mode
  2            /usr/bin/python3     2         manual mode

Press <enter> to keep the current choice[*], or type selection number:

이렇게 시스템의 python 환경을 완료했다.


개발에 사용할 버전 선택하기

개발은 사용할 python 버젼은 virtualenv로 환경을 구축한다.

예를 들어 python 3.6을 사용한다면

python3.6 -m venv .venv

로 가상 환경을 구성한다.

가상 환경은 아래 명령으로 활성화 한다.

. .venv/bin/activate


Practice/Python, Perl

파이썬 프러퍼티 사용하여 일관되게 속성에 접근하라

파이썬의 프러퍼티(property)를 설명한 책과 글은 많음으로 필요성만 살짝 언급하고 지나가겠다.

파이썬에서는 공개 애트리뷰트(public attribute)을 직접 접근(access)하는 것이 관례이다.

class A:
    def __init__(self):
        self.x = 0

a = A()
a.x = 1
print('{}'.format(a.x))

그런데, 비공개(private) 애트리뷰트[각주:1]가 필요한 경우가 있다.
이들을 외부에서 접근하기 위해서는 엑세스 함수-즉 get_xxx(), set_xxx()와 같은 것-을 사용해야 한다.
접근 형식이 관례와 달아서 표현의 일관성이 깨지는 것이 문제이다.[각주:2]
이럴 때, 프러퍼티를 사용하면 동일한 표현 형식으로 접근이 가능하다.

class A:
    def __init__(self):
        self.x = 0
        self.__y = 0

    @property
    def y(self):
        return self.__y

    @y.setter
    def y(self, value):
        self.__y = value


a = A()
# attribute access
a.x = 1
print('{}'.format(a.x))
# property access
a.y = 2
print('{}'.format(a.y))

아래 코드처럼 엑세스 함수를 사용하면, 즉, a.x와 a.set_y()를 섞어쓰면, 더럽지 아니한가?

class A:
    def __init__(self):
        self.x = 0
        self.__y = 0

    def get_y(self):
        return self.__y

    def set_y(self, value):
        self.__y = value


a = A()
# attribute access
a.x = 1
print('{}'.format(a.x))
# getter/setter access
a.set_y(2)
print('{}'.format(a.get_y()))

매우 드물기는 하지만, 엑세스 함수의 오버라이딩(overriding)이 필요할 때가 있다.
그러한 경우, 아래 예제 코드를 참고하여 작성하도록 한다.[각주:3]

class A:
    def __init__(self):
        pass

    @property
    def x(self):
        return self.__x

    @x.setter
    def x(self, value):
        self.__x = value


class B(A):
    def __init__(self):
        super().__init__()

    @A.x.setter
    def x(self, value):
        if value < 0:
            raise ValueError('x below 0 is not possible')
        super(B, B).x.__set__(self, value)


class C(B):
    def __init__(self):
        super().__init__()

    @B.x.setter
    def x(self, value):
        if value > 100:
            raise ValueError('x above 100 is not possible')
        super(C, C).x.__set__(self, value)

데코레이션 패턴(decoration pattern)이 상속보다 더 유용할 수 있다.
예를 들면, getter에 캐싱 기능을 추가하는 경우가 그러하다.
데코레이션 패턴으로 구현하는 것은 본 글의 취지와 맞지 않아서 생략한다.


참고 링크:

  1. 관례적으로 '__'로 시작하면 비공개 애트리뷰트이다. [본문으로]
  2. 코드가 더러워진다. [본문으로]
  3. 그 동안의 실무 경험에서 깨달은 한가지 교훈. "때때로 백번의 설명보다 한번의 예제가 낫다." [본문으로]
Practice/Coding, Debugging

기본 값(default value)을 언제 사용할까?

얼마 전, 기본 매개변수(default parameter) 때문에 문제를 겪었다.
큰 규모의 리펙토링 후에 문제가 발생했다.
이 함수를 호출할 때 문제의 매개변수를 누락한 것이 원인이다.
그러나, 기본 값이 있어서 오류가 드러나지 않았고,
테스트에 사용한 값이 오류를 보여주지 못하는 값이었다.[각주:1]

위 사건 이후로 기본 값에 대해서 고민하게 되었다.

매번 값을 특정하는 것은 꽤 귀찮은 일이다.
가령, ssh 접속할 때 포트 번호 22를 항상 입력하는 것은 불편하다.
기본 값[각주:2]은 이런 불편함을 덜어준다.
이는 곧 개발의 생산성과 사용의 편의성으로 이어진다.
한편으로는, 이것이 나중에 문제가 되기도 한다.

기본 값을 사용하는 원칙을 하나 정하자.
명백하고 합리적으로 그 값을 대부분 사용하면 기본 값이 될 수 있다.

예를 들면, 일반적인 HTTP 클라이언트를 개발한다면,
HTTP 프로토콜의 기본 포트인 80을 기본 값으로 사용할 수 있다.

한편으로는, 사내 HTTP API 서버들의 포트가 다양하다면,
또는 개발 서버와 테스트 서버, 실 서버 간에 포트가 다르다면,
포트에 기본 값을 지정할 지 고민이 필요하다.

데이터베이스 테이블과 클래스 이름 간에 생성 규칙[각주:3]이 있다면,
테이블의 이름을 생략할 수 있다.
멤버 변수나 함수의 인자의 기본 값으로 클래스 명에서 도출된 테이블 이름을 사용한다.

'일단 이 값을 기본으로 하자.'와 같은 위험천만한 기본 값은 조심해야 한다.[각주:4]
당장은 개발의 생산성으로는 이어진다.
하지만, 이것은 기술 부채가 되어 자신의 발목을 잡을 것이다.
기본 값은 명백하고 합리적인 접근으로 판단해야 한다.

  1. 이 매개변수는 함수의 로직에서 중요한 것이 아니었기 때문에 크게 신경쓰지 않았다. [본문으로]
  2. 하드 코딩, 기본 매개변수 등 [본문으로]
  3. Convention over Configuration [본문으로]
  4. 문제의 탐색에서의 기본값은 괜찮다. [본문으로]
Life/Software Engineer

'T'자형 폴리글랏 프로그래밍

초보 기능인과 장인

개발자는 기능인이다.
초보 기능인에서 장인으로 거듭나기 위해서
끊임없는 공부와 훈련으로 기술을 갈고 닦아야 한다.

초보 기능인이 "할 줄 안다." 정도의 수준이라면
장인은 "훌륭히 잘 해낸다."라고 말할 수 있다.
장인은 작업 효율도 뛰어나지만, 무엇보다도 완성도가 매우 높다.


'T'자형 인간

예전에는 하나만 잘해도 괜찮은 시대였다.[각주:1]
요즘엔 하나만 잘해서는 힘들다.
자기 전공 이외에도 다방면으로 두루두루 알아야 한다.
이런 사람들을 소위 'T'자형 인간이라고 부른다.

다만, 'T'자의 머리처럼 넓고 얕은 지식만 중요한 것이 아니라,
수직의 몸통처럼 깊이도 존재하는 것을 잊으면 안된다.
자신의 전문 분야에 대해서 깊은 경지에 도달해야 하는 것은 예나 지금이나 마찮가지이다.


'T'자형 폴리글랏 프로그래머

프로그래밍 언어나 라이브러리, 프레임워크를 많이 아는 것을 실력으로 여기는 경우가 왕왕 있다.
한가지에 대해서 초급 기능인이 되는 것은 보통 일주일이면 가능하다.
그래서, 맛보기 수준[각주:2]으로 많이 아는 것이 실력은 아니다.

그거 할 수 있어?
라는 질문에
할 줄 알아
정도는 실력이라고 말하기 힘들다.

주력 분야에서 우아한 설계와 코딩을 할 수 있어야 최소한의 기본기를 가졌다고 할 수 있다.
깊이 있는 경험 없이 그저 얕게만 많이 아는 것은, 집은 넓고 큰데 기둥이 부실한 것과 같다.
위태롭고 쉽게 부서지는 코드를 다양한 방식으로 만들 수 있을 뿐이다.

이전 질문에

그거 잘 해
라고 말할 수 있어야 실력이다.

특정 분야의 철학과 장점을 제대로 이해하고 활용하여 아름다운 코드를 만들려면
해당 기술에 대한 상당한 공부와 훈련 그리고 실전 코딩 경험이 필요하다.
다른 분야를 기웃거리더라도[각주:3] 주력 기술 한두가지는 꾸준히 연마해야 한다.
넓고 얕은 폴리글랏이 아닌 'T'자형 폴리글랏 프로그래머가 진짜 실력이다.

  1. "한 우물만 파라."는 속담까지 있다. [본문으로]
  2. 작은 프로젝트 한두개 정도까지도 맛보기 수준 [본문으로]
  3. 새로운 분야를 꾸준히 살펴보는 것이 좋다. 다른 패러다임은 사고의 지평을 넓혀준다. [본문으로]

알림

이 블로그는 구글에서 제공한 크롬에 최적화 되어있고, 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.

카운터

Today : 41
Yesterday : 120
Total : 208,962