웹서핑을 하다가 무심코 알게된 왕 저렴한 호스팅 서비스...

    - https://www.clien.net/service/board/use/12730123?od=T31&po=2&category=&groupCd=



엄청난 지연 속도로 솔직히 우리나라에서 사용하기에 어려움이 많은 호스팅 서비스이지만,

뜬금없는 서비스 사용 장애를 보이기도 한다고는 하지만,

저렴한 맛에 공인 IP를 갖고 있는 리눅스 머신을 하나 갖고 싶다는 욕심에 과감히 질렀는데....



서버 하나 만들어서 Ubuntu 16.04 하나 올리고... locale 잡아주고 환경 설정 좀 해줬는데...


   "그런데, 이젠 뭘하지?"




그러다가 문득... 챗봇 하나 만들어볼까?!


예전에 텔레그램 챗봇 만든다고 AWS에서 lambda 서비스 같은거 가지고 장난해봤는데...

이번엔 "카카오톡"을 대상으로 하나 만들어보자! 라는 생각이 불끈(?) !!!




그런데... 자료를 찾다보니...

    - https://github.com/plusfriend/auto_reply



API형 스마트채팅 신규 등록을 2018년 11월 30일부터 중단한단다... 이런!

뭐 그래도 그 안에 등록을 하면 2019년까지는 사용할 수 있다니

지금 발견(?)한 것이 다행이다~!!! 1년간 재미있게 사용하면 된거지 뭐~!!







만들어보고자 하는 채팅 봇의 개발/운영 환경은 다음과 같다.


    - 채팅 봇이 위치할 곳은 "공인IP를 갖고 있는 Ubuntu 16.04 LTS 환경"

    - 채팅 봇은 Python 2.7.x 버전으로 구현

    - 가능한 기본 라이브러리로만 구현




이제 하나씩 해보자.





1. 플러스친구 앱 생성


    - 채팅 봇이라는 것이 결국은 한 명의 사람 역할을 하는 것이니만큼, 별도의 계정이 필요하다.

    - 그래서 카카오에서는 플러스친구라는 것을 제공해준다. 아래 링크에서 신규로 등록하자.


        . https://center-pf.kakao.com/


    - 내 비즈니스(?)를 위한 방을 하나 만들고, 그 안에서 실제 일을 할 플러스친구를 하나 만드는 것이다.



    - 음... 과금문제가 궁금했는데... 무료로 메시지 1000건은 보낼 수 있다보다.

    - 그런데... 보다보니 내가 생각한 메시지가 아닌가보다. push로 보내는 광고같은 메시지가 1000건 제한인가보다.

    - 대화는 그냥 막해도 되나보다~ 으음?! 좋은데?! 그런데, 카카오톡의 지명도에 비해 채팅 봇은 조용하지?!





2. 채팅 봇 등록 맛보기


    - 카카오톡에서는 "앱"이라는 이름으로 지칭하는 것 같은데, 난 내마음대로 "채팅 봇"이라고 지칭할거다!


    - 플러스친구 관리 페이지를 보면 왼쪽 메뉴 중에 "스마트채팅"이라는 것이 있다. 한 번 클릭해보자.



    - 우리는 대화형 "채팅 봇"을 만들 것이니 당연히 오른쪽의 "API형"으로 설정하면 된다.



    - 어!? 그런데... "앱 URL"엔 뭘 넣어야 하지?! "API테스트"는 또 뭐고?!


    - 상태를 보아하니.... 일단 뭘 만들고 난 이후에 여기에 등록을 해야할 것 같다. 친절하지 않은 카카오 !!!






3. 기본 코드 만들


    - "앱 등록"을 위한 기본적인 python 코드를 만들어보자.


#!/usr/bin/env python

#-*-coding: utf-8-*-


import os

from flask import Flask, request, jsonify


app = Flask(__name__)


@app.route('/keyboard')

def Keyboard():


    contents = {

        "type"     : "buttons",

        "buttons" : [ "살아있어" ]

    }


    return jsonify( contents )



if __name__ == "__main__":

    app.run( host = '0.0.0.0', port = 7000 )


    - 위 코드를 저장한 다음에 실행을 하고자 하면 에러가 나올 수도 있다.


Traceback (most recent call last):

  File "./whatwant.py", line 5, in <module>

    from flask import Flask, request, jsonify

ImportError: No module named flask 


    - 귀찮더라도 추가 패키지 설치를 해주자.


$ sudo apt-get install python-flask


    - "채팅 봇"을 운영하기 위해서는, 웹서버 역할을 할 아이가 필요하다.

    - 별도로 웹서버를 띄우면 번거로우니, flask로 간단히 해결하고자 하는 것이다.






4. 앱 등록하기


    - 이제 등록하자 !!!


    - 위에 만든 코드를 일단 실행하자.


$ chmod +x ./whatwant.py


$ ./whatwant.py

 * Running on http://0.0.0.0:7000/ (Press CTRL+C to quit)


    - "앱 URL"에 python이 실행되고 있는 서버의 주소를 써주고선 "API 테스트"를 클릭해보자.



    - 제대로 값이 리턴된 것을 확인할 수 있다. 앗싸~!!!

    - 일단 등록까지는 마쳤다!!!








5. 스마트채팅 시작하기


    - 실제 카카오톡에서 정상적으로 동작하기 위해서는 등록된 앱을 시작시켜줘야 한다.



    - 오른쪽에 있는 API형을 시작하면 된다.

    - 카카오톡에서 등록된 플러스친구를 찾아 1:1 채팅을 하면 뭔가 나오는 것을 볼 수 있을 것이다.









6. 미세먼지 정보를 얻어오기 위해서


    - 음... 개인적인 목적으로 우리 동네의 미세먼지 정보를 불러오는 아이를 만들고 싶었다.

    - 그래서 찾아본 미세먼지 정보 API를 제공해줄 수 있는 곳...


        . https://www.data.go.kr


    - 아래와 같이 공공데이터포털의 오픈 API 부분을 보면 원하는 것을 찾을 수 있다.



    - 회원가입 후, 로그인을 하고...



    - 위와같이 대기오염정보 조회 서비스를 찾을 수 있다.



    - "활용신청"을 누르면 공짜로 즉시 승인되어 API를 사용할 수 있게 된다... 하지만...



    - Chrome에서 들어가려고하니... 위와 같이... 이런! 파일 다운로드는 하지 않을건데... 그럼에도... 결국은 IE에서...




    - 개발을 목적으로 하는 것과 운영을 목적으로 하는 것을 구분하는 것 같다. 개발용도로도 24개월간은 지원해준다.



    - 마이페이지를 통해서 등록된 서비스를 볼 수 있다. 즉시 승인이라고는 하는데...

    - 서버에 실제 등록되기까지에는 시간이 좀 걸리는 것 같다. (즉, 바로 사용이 안된다)



    - "일반 인증키" 발급 신청을 하면 위와 같이 일반 인증키가 나오는데, 이걸 이용해서 API를 사용할 수 있는 것이다.

    - 미리보기를 이용하면 샘플처럼 결과를 확인할 수 있는데, 필자 같은 경우 1시간 정도 후에 가능했다.





7. 뭔가 그럴듯한 코드 만들기


    - 미세먼지 정보를 얻어올 수 있는 API까지 확보를 했으니 코드를 만들어 보자.


    - 위에서 만든 코드 파일을 개선시켜보겠다.


#!/usr/bin/env python

# -*- coding: utf-8 -*-


import os

import requests

from flask import Flask, request, jsonify


app = Flask(__name__)



@app.route('/keyboard')

def Keyboard():


    return jsonify( {"type" : "text"} )





@app.route('/message', methods=['POST'])

def message():


    content = request.json['content']


    if( u"안녕" in content ):

        contents = { 'message': { 'text' : u"안녕하세요" } }


    elif( u"사랑" in content ):

        contents = { 'message': { 'text' : "저도 사랑해요" } }


    elif( u"뭐야" in content ):

        contents = { 'message': { 'text' : "저도 제가 뭔지 모르겠어요" } }


    elif( u"미세먼지" in content ):

        url  = "http://openapi.airkorea.or.kr/openapi/services/rest/"
        url += "ArpltnInforInqireSvc/getMsrstnAcctoRltmMesureDnsty"
        url += "?serviceKey=1234"
        url += "&numOfRows=10&pageSize=10&pageNo=1&startPage=1"
        url += "&dataTerm=DAILY&ver=1.3&_returnType=json"
        url += "&stationName=%EB%8F%99%ED%83%84"

        r = requests.get( url )

        contents = { 'message': { 'text' : "죄송합니다만, 미세먼지 정보를 확인하지 못했어요!" } }
        if( r.status_code == 200 ):

            items = r.json()
            if( 'list' in items.keys() ):

                item  = u"%s 측정된" % items['list'][0]['dataTime']
                item += u"\n동탄의 미세먼지는"
                item += u"\npm10=%s, pm25=%s 입니다" % (items['list'][0]['pm10Value'], items['list'][0]['pm25Value'])
                item += u"\n24시간 예측값은"
                item += u"\npm10=%s, pm25=%s 입니다" % (items['list'][0]['pm10Value24'], items['list'][0]['pm25Value24'])
                item += u"\n입니다."

                contents = { 'message': { 'text' :  item } }

    else:
        contents = { 'message': { 'text' : content + u"가 무슨 말이야?" } }

    return jsonify( contents )


if __name__ == "__main__":
    app.run( host = '0.0.0.0', port = 7000 )


    - button 등을 이용한 대화법도 있지만, 그냥 사람같은 대화를 원해서 위와 같이 해봤다.


    - 서버에 채팅 봇을 계속 띄워놓기 위해서는 다음과 같이 실행하면 된다.


$ ./whatwant.py &


    - 제대로 서비스 하려면 log도 남겨야 할 것 같고 뭐 기타 등등 해야할게 많을 것 같다.

    - 하지만, 지금은 그냥 그럴듯하게만 하면 되는게 목표니 여기까지만~^^






8. 테스트 하기


    - 스마트폰 화면 캡쳐가 귀찮아서.... 말로 떼우기.... ^^


    - "채팅 봇"을 껐다 켰다가 하면 카카오톡에서 대화할 때 대화를 계속 입력할 수 없을 수도 있다.

    - 이럴 때엔 대화방 나갔다가 다시 1:1 채팅걸면 된다.


    - flask를 이용해서 웹서버처럼 돌리다보니 python 에러메시지가 잘 나오지 않는다.

    - 가능하면 별도로 코드 테스트를 한 뒤에 채팅 봇에 코드 넣는 것이 좋다.

    - 아니면 중간에 계속 print 찍어야 할 수도....


    - 일단 위와 같이 하면 아래와 같이 잘 된다~ ^^


끝~ ^^


반응형

삼성 스마트TV를 제대로 사용해보기 위해서 AllShare 기능을 설정해보고자 했다.
최근에는 삼성링크라는 이름으로 제공해주고 있는 서비스다.

그러나 사실 원하는 만큼의 깔끔함이나 원활한 기능을 제공해주고 있지는 못하고 있고
더군다나 최근에는 거의 버린 서비스라는 느낌이 확~

음... 내가 이런 말을 하면 안되는데.... 음... 안되는데...

뭐 여하튼...

그래서 해당 기능을 서버에서 제거해버렸는데 여전히 남아있는 흔적이 있었다.
동영상 파일마다 삼성링크가 만들어낸 [ *.mta ] 파일들이 바로 그것이다.


해당 파일들을 찾아서 지우는 일을 하고 싶어서... Python을 이용해보려 했다.


1. Windows 환경에서 Python 실행하기

   - http://whatwant.tistory.com/703 
 

2. 스크립트 만들기

   - 아래와 같이 간단한 스크립트로 찾아서 지웠다.


#!/usr/bin/python

# -*- coding: utf-8 -*-


import os

import sys


EXT = '.mta'


if __name__ == "__main__":


        if len(sys.argv) < 2:

                sys.exit('Usage: %s path' % sys.argv[0])

        if not os.path.isdir(sys.argv[1]):

                sys.exit('ERROR: %s was not found!' % sys.argv[1])

        PATH_TARGET = sys.argv[1]


        for root, dirs, files in os.walk( PATH_TARGET ):


                for file in files:

                        ext = os.path.splitext( file )

                        if EXT == ext[1]:

                                os.remove( os.path.join(root,file) )


        exit()



   - 예외 사항 등에 대한 고려가 없었기에 위험한 코드일 수도 있다. 주의!!!

 
반응형

개인적으로 업무용 운영체제로는 리눅스가 가장 좋다고 생각하기에
윈도우즈 환경에 대해서는 그다지 알아보지도 않고 사용하지도 않고 있다.

회사에서도 우분투를 메인 운영체제로 사용하고 있고 필요에 따라 VirtualBox로 윈도우즈 환경을 사용하고 있다.
VBox의 윈도우즈 환경을 사용하긴 하지만, 공용폴더를 이용하여 중요한 파일 관리는 모두 우분투 환경에서 하고 있다.

그래서 지금까지는 파일을 다루거나 하는 스크립트를
그냥 파이썬(Python)으로 만들어서 사용하는데 아무런 문제가 없었다.


그런데, 최근 미니서버를 돌리면서 여러가지 이슈로 윈도우즈 환경을 구축했는데,
해당 서버에서 어떤 파일을 다뤄야 하는 스크립트가 필요한데...
윈도우즈 환경이다보니 파이썬 실행환경을 맞춰줘야 하게 되어서 알아보고자 한다.


공식홈페이지
   - https://www.python.org/


윈도우즈 환경을 위한 패키지도 제공을 해주고 있다.
3.x 버전과 2.x 버전을 제공해주고 있는데... 호환성을 위해 2.x 버전으로 설치를 하자.

설치할 때에 PATH 부분도 추가를 해주는 것이 편리하다.



설치가 모두 잘 되면, 실행해보자.


위와 같이 빠져나올 때엔 "exit()"를 실행하면 된다.


반응형

GitPython을 가지고 뭔가 만들다가 에러를 만났다.


fetch()를 실행하는데, 뭔가가 맞지 않다고 에러라고 하는데... 아무리 살펴봐도 에러가 발생한 상황이 아닌데...
그래서 찾아봤는데 이는 GitPython이 최신 버전의 Git 과의 궁합에서 발생한 에러/버그 상황이다.

   https://github.com/gitpython-developers/GitPython/issues/142

해결 방법은 파일 수정이라고 한다.

$ sudo nano /usr/local/lib/python2.7/dist-packages/GitPython-0.3.2.RC1-py2.7.egg/git/remote.py

...
        def _get_fetch_info_from_stderr(self, proc, progress):
                # skip first line as it is some remote info we are not interested in
                output = IterableList('name')

                # lines which are no progress are fetch info lines
                # this also waits for the command to finish
                # Skip some progress lines that don't provide relevant information
                fetch_info_lines = list()
                for line in digest_process_messages(proc.stderr, progress):
                        if line.startswith('From') or line.startswith('remote: Total'):
                                continue
                        elif line.startswith('warning:'):
                                print >> sys.stderr, line
                                continue
...

위와 같은 코드를 아래와 같이 변경하면 된다고 한다.

...
        def _get_fetch_info_from_stderr(self, proc, progress):
                # skip first line as it is some remote info we are not interested in
                output = IterableList('name')

                # lines which are no progress are fetch info lines
                # this also waits for the command to finish
                # Skip some progress lines that don't provide relevant information
                fetch_info_lines = list()
                for line in digest_process_messages(proc.stderr, progress):
                        #if line.startswith('From') or line.startswith('remote: Total'):
                        if line.startswith('From') or line.startswith('remote: Total') \
                                or line.startswith('POST') or line.startswith(' ='):
                                continue
                        elif line.startswith('warning:'):
                                print >> sys.stderr, line
                                continue
...

그런데, 위와 같이 하여도 에러는 여전하였다.

Git을 다룬다는 것 자체도 좀 마이너하고, 특히나 GitPython을 다루는 분들이 많지 않고...
자료를 찾기가 너무 어려워서 다시 원점으로 돌아가서 현재 개발중인 코드를 살펴보다가 답을 찾았다.

...
                # read head information
                fp = open(join(self.repo.git_dir, 'FETCH_HEAD'),'r')
                fetch_head_info = fp.readlines()
                fp.close()

                assert len(fetch_info_lines) == len(fetch_head_info), "len(%s) != len(%s)" % (fetch_head_info, fetch_info_lines)

                output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line)
                                                for err_line,fetch_line in zip(fetch_info_lines, fetch_head_info))

                finalize_process(proc)
                return output
...

에러메시지를 출력하는 부분이 위와 같이 있는데, 그냥 확 주석처리해버리면 된다.

...
        # read head information
        fp = open(join(self.repo.git_dir, 'FETCH_HEAD'),'r')
        fetch_head_info = fp.readlines()
        fp.close()
       
        # NOTE: HACK Just disabling this line will make github repositories work much better.
        # I simply couldn't stand it anymore, so here is the quick and dirty fix ... .
        # This project needs a lot of work !
        # assert len(fetch_info_lines) == len(fetch_head_info), "len(%s) != len(%s)" % (fetch_head_info, fetch_info_lines)
       
        output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line)
                        for err_line,fetch_line in zip(fetch_info_lines, fetch_head_info))
...

프로젝트 담당자도 인정했다시피 이렇게 주석처리하는 것이 정석은 아니다.
여력이 되시는 분은 이 부분에 대해서 도움을 주면 좋을 것 같다.


뭐 여하튼... 문제 해결!!!

반응형

Git의 데이터들을 다루기 위해서 Python을 이용해서 스크립트를 종종 만들고 있다.

지금까지는 subprocess를 사용해서
외부 명령어(git)를 실행하고 그 결과를 String으로 받아서 파싱하는 방식으로 만들었는데...
(혼자서 나만의 Git Class를 만들어서, 쿵짝쿵짝... ^^)


Python Library로 제공되는 것이 있지 않을까 좀 찾아보았더니... 당연히(?) 있다!

GitPython 0.3.2 RC1 (Python Git Library) : 2011-07-06
   https://pypi.python.org/pypi/GitPython/0.3.2.RC1

Package Documentation
   GitPython is a python library used to interact with Git repositories.

Author                            : Sebastian Thiel, Michael Trier
Documentation                : GitPython package documentation
Home Page                     : http://gitorious.org/projects/git-python/
License                          : BSD License
Requires                         : gitdb (>=0.5.1)
Package Index Owner      : Sebastian.Thiel, mtrier
Package Index Maintainer : Sebastian.Thiel
DOAP record                   : GitPython-0.3.2.RC1.xml

gitdb 0.5.4 (Git Object Database) : 2011-07-05
   https://pypi.python.org/pypi/gitdb

Package Documentation
   GitDB is a pure-Python git object database

Author                       : Sebastian Thiel
Documentation           : gitdb package documentation
Home Page                : https://github.com/gitpython-developers/gitdb
License                     : BSD License
Requires                    : async (>=0.6.1), smmap (>=0.8.0)
Package Index Owner : Sebastian.Thiel
DOAP record              : gitdb-0.5.4.xml


Ubuntu를 사용하게 되면 정말 편리한 점 중에서 한 가지가 바로 Package 관리인데...
주어진대로 사용을 하면 편리하지만, 직접 설치해서 뭔가 하려하면 오히려 번거로운 부분도 많다.

Python도 마찬가지인데 Python과 관련된 전부를 다운로드 받아서 직접 설치한 것이 아니라면
그 외 나머지들도 그냥 패키지로 설치하는 것이 편리하다.

위의 라이브러리들도 마찬가지인데...
이미 Python을 Ubuntu에서 제공하는 패키지로 설치해서 사용하고 있기에,
그냥 Ubuntu에서 제공해주는 패키지로 설치를 해보려고 했는데...

아래와 같이 하면 설치는 되는데... Ubuntu 버전에 따라 제공하는 버전이 다르다.

$ sudo apt-get install python-git

현재(2014.06) 제공하는 버전은 아래와 같다.

 Version  Release   python-git version 
 14.04  Trusty Tahr  0.3.2~RC1-3 
 13.10  Saucy Salamander  0.3.2~RC1-2 
 13.04  Raring  0.3.2~RC1-1
 12.04  Precise Pangolin  0.1.6-1
 10.04  Lucid Lynx  0.1.6-1 

위와 같이 설치하면 편하기는 하지만, 쓸데없는(?) 부가 패키지들도 같이 설치를 한다.

$ sudo apt-get install python-git
패키지 목록을 읽는 중입니다... 완료
의존성 트리를 만드는 중입니다      
상태 정보를 읽는 중입니다... 완료
다음 패키지를 더 설치할 것입니다:
  git git-man liberror-perl libjs-jquery python-async python-gitdb python-smmap
제안하는 패키지:
  git-daemon-run git-daemon-sysvinit git-doc git-el git-email git-gui gitk gitweb git-arch git-bzr
  git-cvs git-mediawiki git-svn javascript-common
다음 새 패키지를 설치할 것입니다:
  git git-man liberror-perl libjs-jquery python-async python-git python-gitdb python-smmap
0개 업그레이드, 8개 새로 설치, 0개 제거 및 0개 업그레이드 안 함.
3,780 k바이트 아카이브를 받아야 합니다.
이 작업 후 23.5 M바이트의 디스크 공간을 더 사용하게 됩니다.
계속 하시겠습니까? [Y/n]

특히 git과 관련한 패키지들도 설치를 하게 되는데, git을 source로 직접 설치한 경우 불필요하고 번거롭기만 하다.


그러면, python-git을 개별 설치하려면 어떻게 해야할까?!
원하는 최신 버전으로 설치하기 위해서는 다음과 같이 수행하자.

$ sudo apt-get install python-setuptools python-dev
$ sudo easy_install GitPython

간단하다.
현재(2014.06) 설치되는 버전은 '0.3.2~RC1'이다.



잘 동작하는지 테스트를 해보기 위해서는 다음과 같이 해보자.



아래 샘플 코드로 돌려보자~

#!/usr/bin/python
# -*- coding: utf-8 -*-

import git
import os
import sys
import time

if __name__ == "__main__":

        #for i in range(len(sys.argv)):
        #       print "sys.argv[%d] = '%s'" % (i, sys.argv[i])

        #repo = git.Repo.clone_from( URL_SOURCE, PATH_TARGET )


        if len(sys.argv) < 2:
                sys.exit('Usage: %s repository-name' % sys.argv[0])

        if not os.path.isdir(sys.argv[1]):
                sys.exit('ERROR: Repository %s was not found!' % sys.argv[1])


        PATH_TARGET = sys.argv[1]
        repo = git.Repo( PATH_TARGET )

        for remote in repo.remotes:
                print "[ " + str(remote) + " branches ]"

                for branch in getattr(repo.remotes, str(remote)).refs:
                        print " " + str(branch).replace( str(remote)+"/", "" )

                        for commit in repo.iter_commits(branch, max_count=3):

                                print ""
                                print "         Commit          : ", commit
                                print "         Author          : ", commit.author, ", (",
                                print time.asctime(time.gmtime(commit.authored_date)), ")"
                                print "         Committer       : ", commit.committer, ", (",
                                print time.asctime(time.gmtime(commit.committed_date)), ")"
                                print "         Encoding        : ", commit.encoding
                                print "         Summary         : ", commit.summary
                                print "         Delta LOC       : ", commit.stats.total['lines'], " (+",
                                print commit.stats.total['insertions'], ", -",
                                print commit.stats.total['deletions'], ")"
                                #print commit.stats.files
                                #print "                Message         : ", commit.message
                                #print "                Parents         : ", commit.parents

        print ""

        print "[ Local branches ]"
        for branch in repo.branches:
                print " " + str(branch)

                #commits = list( repo.iter_commits(branch, max_count=10) )

                for commit in repo.iter_commits(branch, max_count=3):

                        print ""
                        print "         Commit          : ", commit
                        print "         Author          : ", commit.author, ", (",
                        print time.asctime(time.gmtime(commit.authored_date)), ")"
                        print "         Committer       : ", commit.committer, ", (",
                        print time.asctime(time.gmtime(commit.committed_date)), ")"
                        print "         Encoding        : ", commit.encoding
                        print "         Summary         : ", commit.summary
                        print "         Delta LOC       : ", commit.stats.total['lines'], " (+",
                        print commit.stats.total['insertions'], ", -",
                        print commit.stats.total['deletions'], ")"
                        #print commit.stats.files
                        #print "                Message         : ", commit.message
                        #print "                Parents         : ", commit.parents


공식 매뉴얼과 가이드는 다음에서 확인할 수 있다.

   http://pythonhosted.org/GitPython/0.3.2/tutorial.html
   http://pythonhosted.org/GitPython/0.3.2/reference.html

반응형


Python script 파일을 만들어서 실행을 하다보면,
script 파일이 지금 현재 어느 경로에 위치하고 있는지 알고 싶은 경우가 있다.

이럴 때 사용할 수 있는 좋은 예약어가 하나 있다.

__file__


현재 실행 중인 스크립트 파일 이름을 의미한다.
단순한 파일 이름이 아니라 실행할 때 사용한 경로를 포함한 파일 이름이다.

테스트를 위해서 [ dir.py ]라는 이름의 Python script 파일을 다음 내용으로 생성해보자.

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os

if __name__ == "__main__":

        print "__file__                                                       = " + __file__
        print "os.path.dirname(__file__)                              = " + os.path.dirname(__file__)
        print "os.path.realpath(__file__)                              = " + os.path.realpath(__file__)
        print "os.path.realpath( os.path.dirname(__file__) )   = " + os.path.realpath( os.path.dirname(__file__) )
        print
        print "os.getcwd()                                                 = " + os.getcwd()
        print
        print "os.path.basename( os.path.realpath(__file__) ) = " + os.path.basename(__file__)


실행을 해보면 다음과 같다.

$ pwd
/srv/workspace/barerepo

$ python ./dir.py
__file__                                                       = ./dir.py
os.path.dirname(__file__)                              = .
os.path.realpath(__file__)                              = /srv/workspace/barerepo/dir.py
os.path.realpath( os.path.dirname(__file__) )   = /srv/workspace/barerepo

os.getcwd()                                                 = /srv/workspace/barerepo

os.path.basename( os.path.realpath(__file__) ) = dir.py


dirname 은 상대경로를 알려주고 realpath 는 절대경로를 알려준다.
 
[ __file__ ] 예약어를 통해서 현재 경로를 확인하는 것에 대해서 살펴보고 있지만,
사실 지금 현재 경로를 알고 싶을 때에는 [ os.getcwd() ] 명령이 훨씬 더 많이 사용된다.

경로에서 파일이름만 뽑아내고 싶을 때에는 [ os.path.basename() ] 명령을 사용하면 된다.

반응형

Linux 환경에서 build (compile) 시간을 짧게하기 위한 방법을 찾아보면 꼭 나오는 방법이 있다.
바로 ccachedistcc 다!

여기에서는 ccache에 대해서 알아보겠다.

원리는 비교적 간단하다.
처음에 빌드를 할 때에 정보와 함께 그 결과물을 저장하고 있다가,
다음 번 빌드를 할 때엔 정보를 비교해서 같은 파일의 빌드를 한다면 저장하고 있는 결과물을 활용하는 것이다.
그렇게 함으로써 두 번째 빌드부터는 변경된 부분만 빌드를 수행하므로 소요시간이 짧아지는 것이다.




1. 공식 사이트

     - http://ccache.samba.org/
     - License : GPL3

     - 기본적으로 gcc 컴파일에 적용을 할 수 있으며, Cross-compiler (Tool-chain)에도 적용할 수 있다.

     - 안전성에 대해서는 나름 자부를 하고 있는 상당히 오래된 프로젝트이며,
       구글의 안드로이드에서도 공식적으로 옵션으로 적용을 하고 있다.




2. Install

     - Ubuntu에서는 편하게 패키지로 제공을 해준다.


$ sudo apt-get install ccache

     - 이걸로 끝이다. 간단하지 않은가 ?!




3. PATH

     - ccache를 활용하기 위해서는 PATH 설정만 해주면 된다.


$ sudo nano /etc/environment

PATH="/usr/lib/ccache:......."

     - 환경파일에서 PATH 값에서 제일 앞에 "/usr/lib/ccache:" 경로를 추가해주면 된다.
     - 일단은 이러면 끝이다.




4. Environment

     - 그러면 대체 왜 "/usr/lib/ccache" 디렉토리를 경로에 추가를 해줘야할까?


$ cd /usr/lib/ccache

     - 검색해서 자료들을 보면 "export CC='ccache cc'"등을 설정하기도 하고,
       Makefile을 수정하기도 하는 등 다른 방식으로 처리하기도 하지만...
     - 최근엔 그냥 '/usr/lib/ccache' 디렉토리를 이용하면 모든 것이 끝이다.

     - Compiler를 모두 ccache로 대체하면 되는 것이다.

     - 만약 Cross-compiler (Tool-chain)을 사용하는 경우라면 위 디렉토리에 링크를 만들어주면 된다.

$ cd /usr/lib/ccache
$ sudo ln -s ../../bin/ccache powerpc-tuxbox-linux-gnu-cc
$ sudo ln -s ../../bin/ccache powerpc-tuxbox-linux-gnu-c++
$ sudo ln -s ../../bin/ccache powerpc-tuxbox-linux-gnu-gcc
$ sudo ln -s ../../bin/ccache powerpc-tuxbox-linux-gnu-g++






5. cache dir

     - ccache를 적용하면 빌드 결과물을 어딘가에 저장해놓는다고 했는데, 어디에 위치할까?


$ ccache -s

     - 상태(status)를 확인하고 싶을 때 사용할 수 있는 명령이다.

     - 기본적으로는 홈 밑의 ".ccache" 디렉토리에 위치하며, 기본 용량제한은 1GB이다.





6. clear

     - 빌드 결과가 왠지 이상하다거나 cache 데이터를 지우고 싶을 때엔 다음 명령으로 처리할 수 있다.


$ ccache -C




몇 가지 더 옵션들이 있지만, 알고 싶으면 공식 사이트를 참조하기 바란다.
실제로 적용해보면 탁월하게 효과가 있다~!!!

반응형

+ Recent posts