Archive

Posts Tagged ‘python’

vim에 컴파일러/인터프리터의 에러메시지 연동시키기

September 22nd, 2012 No comments

대부분의 IDE에서는, 컴파일 에러나 런타임 에러가 발생했을 때, 소스코드에서 해당 에러의 원인이 된 라인으로 바로 이동하는 기능이 있다.

물론 vim에서도 약간의 설정으로 가능한 기능이다. 설정 및 사용법을 알아보자.

makeprg 설정

우선 현재의 소스코드를 해석하거나 컴파일할 때 사용할 프로그램을 설정한다. 여기서는 python으로 해 보겠다.

:set makeprg=python

이렇게 하고 나면, :make %로 현재 편집중인 파일을 파이썬으로 실행해 볼 수 있다.

errorformat 설정

다음은 vim이 파이썬의 에러메시지를 해석할 수 있도록 에러포맷을 정의해야 한다.

:set errorformat=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m

이제 :make %로 편집중인 소스코드를 파이썬으로 실행했을 때 에러가 발생한다면, 자동으로 커서가 에러가 발생한 위치로 옮겨진다.

파이썬이 출력한 에러메시지에서 어떤 줄이 위의 식에 매칭된다면, vim은 그 줄이 소스코드에서 에러의 원인이 되는 위치를 알려주는 것으로 생각하고 해석하여 파일명, 라인번호 등의 정보를 얻어낸다. 위의 식이라면 %f에 대응하는 것이 파일명, %l에 대응하는 것이 라인번호다.

예를 들어 파이썬이 아래와 같은 메시지를 출력한다면,

Traceback (most recent call last):
File "test.py", line 13, in <module>
    x = MyClass()
TypeError: __init__() takes exactly 2 arguments (1 given)

vim은 두번째 줄을 인식해서 test.py와 줄번호 13을 얻어낼 것이다.

자세한 문법은 :help errorformat으로 확인해보자.

만약 errorformat과 대응하는 에러메시지가 1개 이상이라면, cncp로 각 에러를 오갈 수 있으며, clist로 에러메시지의 목록을 확인할 수 있다.

단축키 한번에 실행하기

매번 :make %을 입력하는 것이 번거롭다면, 다음과 같이 단축키 한번에 실행되도록 할 수도 있다. 다음은 f5 키로 실행하도록 하는 설정이다.

:map<f5> :make %<cr>

설정파일에 설정하기

물론 위에서 언급한 errorformat이나 makeprg의 설정 등은 모두 언어별로 다를 수 밖에 없다. 따라서 vim의 syntax 설정 디렉토리에 넣어두는 것이 좋을 것이다. 파이썬이라면 ~/.vim/syntax/python.vim 파일에 다음의 설정을 추가하면 된다.

set errorformat=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m
set makeprg=python
map<f5> :make %<cr>
Categories: 프로그래밍 Tags: ,

내가 리눅스로 뭘 하고 있는지 로그 남기기 (파이썬)

September 9th, 2012 No comments

지난번 포스팅에서 맥에서 내가 컴퓨터로 무엇을 하고 있는지 기록하는 스크립트를 어떻게 만들었는지에 대해 이야기했었다.

요번엔 리눅스다. 지난번 스크립트는 애플스크립트로 작성되어 맥에서만 동작했지만, 이번엔 리눅스에서 동작할 수 있도록 파이썬으로 작성할 것이다.

이 스크립트의 전체 소스코드는 여기서 받을 수 있다.

만들기

일단 현재 사용중인 윈도를 얻어야 한다. 나는 wnck 모듈을 사용했다. 그냥 쓰기 쉬워보여서.

1
2
3
4
5
6
7
8
import wnck
 
def get_current_window():
    try:
        return wnck.screen_get_default().get_active_window()
    except AttributeError:
        traceback.print_exc(file=sys.stderr)
        return False

이렇게 해서 얻은 윈도에서 프로세스 id를 얻은 다음, 다시 그 프로세스 id에서 프로세스 이름을 얻는다. 윈도 이름은 그냥 get_name() 메소드로 얻을 수 있다.

1
2
3
4
5
6
7
8
9
def log(output):
    // ...
    window = get_current_window()
    name = get_name(window.get_pid())
    window_name = window.get_name()
    // ...
 
def get_name(pid):
    return [ps.name for ps in psutil.get_process_list() if ps.pid == pid][0]

ip, ssid, 날짜도 얻는다. ip하고 ssid는 그냥 ip와 iwconfig를 직접 실행해서 얻었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def get_ip():
    #Use ip route list
    try:
        arg = 'ip route list'    
        p = subprocess.Popen(arg, shell=True, stdout=subprocess.PIPE)
        data = p.communicate()
        sdata = data[0].split()
        ipaddr = sdata[ sdata.index('src')+1 ]
        return ipaddr
    except Exception, e:
        traceback.print_exc(file=sys.stderr)
        return '-'
 
def get_ssid():
    arg='iwconfig'    
    p = subprocess.Popen(arg, shell=True, stdout=subprocess.PIPE, stderr=None)
    for line in p.communicate():
        if line:
            match = re.search('ESSID:"(.*)"', line)
            if match:
                return match.groups()[0]
 
    return '-'
 
def get_date():
    return time.strftime('%Y/%m/%d-%H:%M', time.localtime())

실제로 파일에 기록하는 역할을 하는 log() 함수도 만든다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def log(output):
    try:
        window = get_current_window()
        if not window:
            sys.stderr.write('failed to get window\n')
            return True
 
        format = 'a4'
        output.write("%s %s %s %s %s %s\n" % (
            format, get_ip(), get_ssid(), get_date(),
            get_name(window.get_pid()), window.get_name()))
    except Exception, e:
        traceback.print_exc(file=sys.stderr)
 
    return True

마지막으로 60초에 한번씩 실행되도록 glib.timeout_add 로 설정해주고, gtk.main()을 호출하면 된다.

1
2
glib.timeout_add(60 * 1000, log, output) # 60sec
gtk.main()

문제와 해결방법

osx때는 없었던 문제가 두 가지 정도 있어서 애를 좀 먹었다.

gtk를 사용할 수 없는 환경에서는 실행 불가

이 때문에 osx때 했던 것 처럼 crontab에 넣는 방법은 사용할 수 없다. 그래서 대신 우분투 Startup Applications에 등록했다.

ssid를 알아내려면 루트 권한이 필요

리눅스에서는 iwconfig로 ssid를 알아내려면 루트 권한이 필요하다.

이 문제의 해결방법엔 두 가지가 있다.

단순한 방법: iwconfig가 파일 owner(즉 root)의 권한을 갖고 실행되도록 만들기

sudo chmod +s /sbin/iwconfig

조금 더 정교한 방법: iwconfig가 ssid를 알아낼 수 있도록 권한주기

sudo setcap cap_net_raw,cap_net_admin=eip /sbin/iwconfig

나는 후자를 택했다. 누가 실행하든 root 권한으로 실행된다는 건 좀 겁나니까.

이 해결방법에 더 자세히 알고 싶다면 내가 스택오버플로우에 올린 질문을 보라. TOC라는 분이 매우 친절하게 답변을 달아주었다.

이렇게 해서 나는 osx나 리눅스를 쓸 때 내가 컴퓨터로 무엇을 했는지에 대한 기록을 항상 남기고 있다. 나는 깨어있는 시간의 절반을 컴퓨터 앞에서 보내고 있으니1, 이는 결국 내 인생의 절반에 대한 로그를 남기고 있다는 것과 같다.

현재는 주로 ‘내가 그때 뭘 했더라’나 ‘그걸 하는데 시간을 얼마나 썼더라’를 확인해야 할 때 이용하고 있으며, 가끔씩 내가 컴퓨터로 뭘 주로 하는지 알아보고 싶을때도 사용한다.

추가

로그가 실제로 어떤식으로 남는지 궁금해하실 분들을 위해, 내가 이 글을 작성하는 동안 남은 로그를 올려본다.

a4 192.168.0.22 nori 2012/09/09-01:40 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:41 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:42 gnome-terminal worklog.py (~/mysrc/worklog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:43 chromium-browser Posts ‹ npcode — WordPress - Chromium
a4 192.168.0.22 nori 2012/09/09-01:44 gnome-terminal worklog-py.md (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:45 gnome-terminal worklog.py + (~/mysrc/worklog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:46 gnome-terminal worklog.py (~/mysrc/worklog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:47 chromium-browser wnck python - Google 검색 - Chromium
a4 192.168.0.22 nori 2012/09/09-01:48 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:49 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:50 gnome-terminal worklog-py.md (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:51 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:52 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:53 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:54 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:55 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:56 gnome-session-properties Edit Startup Program
a4 192.168.0.22 nori 2012/09/09-01:57 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:58 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-01:59 gnome-terminal iwconfig (~/wiki) - VIM
a4 192.168.0.22 nori 2012/09/09-02:00 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:01 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:02 gnome-terminal worklog-py.md (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:03 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:04 gnome-terminal worklog-py.md (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:05 gnome-terminal worklog-py.md (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:06 gnome-terminal linux (~/wiki) - VIM
a4 192.168.0.22 nori 2012/09/09-02:07 gnome-terminal worklog-py.md (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:08 gnome-terminal COMMIT_EDITMSG + (~/mysrc/worklog/.git) - VIM
a4 192.168.0.22 nori 2012/09/09-02:09 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:10 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:11 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:12 gnome-terminal worklog-py.md + (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:13 gnome-terminal worklog-py.md (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:14 gnome-terminal worklog-py.md (~/blog) - VIM
a4 192.168.0.22 nori 2012/09/09-02:15 chromium-browser npcode - Chromium
a4 192.168.0.22 nori 2012/09/09-02:16 gnome-terminal  ~/blog
a4 192.168.0.22 nori 2012/09/09-02:17 chromium-browser 새로운 글 추가 ‹ npcode — WordPress - Chromium
a4 192.168.0.22 nori 2012/09/09-02:18 chromium-browser npcode » 내가 리눅스로 뭘 하고 있는지 로그 남기기 (파이썬) - Chromium
a4 192.168.0.22 nori 2012/09/09-02:19 chromium-browser 글 편집 ‹ npcode — WordPress - Chromium
a4 192.168.0.22 nori 2012/09/09-02:20 chromium-browser 글 편집 ‹ npcode — WordPress - Chromium
  1. 이 사실 자체도 이 로그를 통해서 안 것이다. 내가 컴퓨터를 사용하는 시간은 하루 평균 8시간을 약간 넘는 정도다. []
Categories: 프로그래밍 Tags:

PHP, Perl, Ruby, Python 비교

June 2nd, 2011 2 comments

나는 왜 PHP보다 Python을 좋아하는가? 깔끔한 문법이 일단 매력이지만 그게 다가 아니다.

기능 비교1

일단은 언어의 강력함에서 큰 차이를 보인다. 생산성에 신경쓰는 언어들이라면 당연히 지원해 줄 법한 기능들에 대해 PHP는 너무나도 무심하다.

PHP Perl Ruby Python
Higher-order functions Arguments Yes Yes Yes Yes
Results Yes Yes Yes Yes
Non-local variables Nested functions No2 6 Yes Yes
Anonymous functions 5.3 Yes Yes Yes
Closures 5.33 Yes Yes Yes
Partial application No 6 1.94 2.55
List comprehension No No No Yes
Mixin No 6 Yes Yes

Anonymous functions와 Closures를 PHP 5.3에서 지원하기는 하지만 그 기능을 웹애플리케이션을 개발할 때 사용하기엔 PHP 5.3이 너무 최근(2009년)에 나왔다. 내 애플리케이션의 요구사항을 PHP 5.3 이상으로 하는 것은 시기상조다.

성능 비교

아래의 링크를 보면 모든 테스트케이스에서 python이 php보다 훨씬 좋은 성능을 보인다. pypy나 psyco를 사용한다면 상대가 안되는 수준이 될 듯.

  1. http://en.wikipedia.org/wiki/First-class_function, http://en.wikipedia.org/wiki/List_comprehension, http://en.wikipedia.org/wiki/Mixin []
  2. Nested functions are created at global scope once the outer function is executed. []
  3. Anonymous functions could be created using create_function but could not refer to variable in the outer scope. []
  4. Explicit currying with Proc#curry []
  5. Explicit partial application with functools.partial []
Categories: 프로그래밍 Tags: , , ,

프로그래밍 언어들을 한문장으로 소개

February 17th, 2011 1 comment

Perl

Perl is a language optimized for scanning arbitrary text files, extracting information from those text files, and printing reports based on that information.1
펄은 텍스트를 다루는데 최적화된 언어다.

Python

Python is an interpreted, interactive, object-oriented programming language  that  combines  remarkable power with very clear syntax.2
파이썬은 매우 간결한 문법이 특징.
동의한표. 내가 써 본 언어 중에서 가장 문법이 간결했다. 물론 lisp 계열은 제외하고.

Ruby

Ruby is an interpreted scripting language for quick and easy object-oriented programming.3
루비는 빠르고 쉬운 OOP를 위한 스크립트 언어다.
여기서 빠르다는건 성능이 아니라 생산성을 의미하는 것이겠지. 확실히 파이썬보다 코드를 짧게 작성할 수 있다.

PHP

PHP is a widely-used general-purpose scripting language that is especially suited for Web development and can be embedded into HTML.4
PHP는 원래 HTML에 끼워넣는 것에 특화된 언어다.
언어가 좀 엉성해 보이고 빈약해서 난 항상 불만이긴 한데, 어찌보면 그런 점도 이런 지향점을 고려하면 타당한 것일 수 있다.

C++

C++ is a general purpose programming language with a bias towards systems programming that
* is a better C
* supports data abstraction
* supports object-oriented programming
* supports generic programming.5
C++은 C보다 좋은 언어라고 한다.
잘못하면 싸움나겠네.

J

J is a modern, high-level, general-purpose, high-performance programming language.6
현대적 고수준 다목적 고성능 언어.
그리고 C++ 보다도 어려운 것 같아.

Lisp

Lisp is a programmable programming language.7
정말 멋진 정의다!

Java?

자바는 공신력 있고 설득력 있는 한문장 소개를 찾지 못했다. C++ 보다도 정체성이 불분명한 녀석이다.
  1. man perl []
  2. man python []
  3. man ruby []
  4. man php []
  5. http://www2.research.att.com/~bs/C++.html []
  6. http://www.jsoftware.com/ []
  7. 책 <On Lisp>의 서문에서. Paul Graham은 “It’s difficult to convey the essence of a programming language in one sentence, but John Foderaro has come close:” 라고 말하며 이 정의를 소개한다. []
Categories: 프로그래밍 Tags: , , , , , ,