[출처 http://blog.daum.net/_blog/BlogTypeView.do?blogid=0LYny&articleno=6543747#ajax_history_home]


폴더 내에 있는 여러 파일들 중에서 *.txt 인 파일만을 

각 파일 이름들을 리스트로 저장하고 싶습니다. 어떻게 해야 할까요?


예) c:\aaa\bbb 라는 폴더 안에 1.txt, 2.txt. ... 5.txt 가 들어 있습니다. 
그래서 c:\aaa\bbb 라는 폴더에 접근해서 
List = ["1.txt",...., "5.txt"] 이렇게 파일 리스트를 리스트 형식으로 받으려면...?!

 

=>

import! glob 
File_List = glob.glob('c:/aaa/bbb/*.txt') 
이렇게 하면

File_List = [ "c:/aaa/bbb/1.txt" ,"c:/aaa/bbb/2.txt" ,"c:/aaa/bbb/3.txt" , ....]

으로 file  명들이 list로 입력받을수 있음

 

Tip )

 os.path.basename

디렉토리명이 붙은 파일이름에서 파일 이름만 뽑아내는 방법

 

os.path.isdir(file_name)

파일이 디렉토리인지에 대해서 검사를 하는 함수

[출처 : http://mwultong.blogspot.com/2007/04/python-split-path.html]


패스명은 "디렉토리+파일명+확장자"로 이루어져 있습니다. 윈도우의 경우에는 맨 앞에 "드라이브명"도 포함됩니다.

이 패스명을 각각 "디렉토리, 파일명, 확장자"로 분리하는 예제입니다. os.path.split() 등의 함수로 이런 작업을 쉽게 할 수 있습니다.

패스명 분리 예제
스크립트 파일명: example.py
#!/usr/bin/python
# -*- coding: cp949 -*-

import os


s = os.path.split("/My Jukebox/Cool Jazz.mp3")

# 디렉토리명 구하기
print s[0]  # /My Jukebox

# 패스에서 파일명만 구하기
print s[1]  # Cool Jazz.mp3

# 확장자만 구하기
s = os.path.splitext("/My Jukebox/Cool Jazz.mp3")
print s[1]  # .mp3




# 이번에는, 드라이브명까지 포함된 Windows 전용 패스를 취급
s = os.path.splitdrive("D:/My Jukebox/Cool Jazz.mp3")

# 드라이브 이름 (MS윈도우의 경우)
print s[0]  # D:

# 드라이브명이 제거된 패스 구하기
print s[1]  # /My Jukebox/Cool Jazz.mp3



split
splitdrive
splitext
함수는 각 요소들이 들어 있는 리스트(배열)를 반환합니다.
[출처 : http://wiki.dgoon.net/doku.php?id=python:profiling]


Python

파이썬용 프로파일링 툴 중 디군이 써본것들 모음. 나중에 까먹으면 뒤적이면 기억을 되살릴 정도로만 정리한다. 모두 DeterministicProfiling 툴이다.

  • profile
  • cProfile
  • yappi

profile, cProfile 은 언젠가부터 파이썬 빌트인이 되었다. yappi 는 여기에서 구할 수 있다.

Profile

순수 파이썬으로 만들어진 프로파일러다. 기본적으로,

  1. import profile
  2. 프로파일 데이터를 얻을 코드의 실행조각 준비
  3. profile.run 함수에 준비된 코드조각과 결과 데이터가 쓰일 파일 이름을 넘김
  4. 파일 이름을 넘겼다면, 해당 이름을 가진 파일에 프로파일 데이터가 쓰이고,
  5. 그렇지 않은 경우 stdout 으로 결과가 나온다

How to write code

예를 들어 간단히 숫자를 더하는 함수를 분석하고 싶다면,

def test(n=100):
    return sum(x for x in xrange(n))
import profile
profile.run('print(test())')
profile.run('print(test(20))')

이런 식으로 사용할 수 있으며, 결과 파일을 지정해주지 않았으니 실행하면 stdout 으로 결과를 볼 수 있다. 실행 결과는 아래와 같다.

4950
         106 function calls in 0.010 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.010    0.010    0.010    0.010 :0(setprofile)
        1    0.000    0.000    0.000    0.000 :0(sum)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.000    0.000    0.010    0.010 profile:0(print(test()))
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.000    0.000 t.py:1(test)
      101    0.000    0.000    0.000    0.000 t.py:2(<genexpr>)


190
         26 function calls in 0.000 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 :0(setprofile)
        1    0.000    0.000    0.000    0.000 :0(sum)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 profile:0(print(test(20)))
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.000    0.000 t.py:1(test)
       21    0.000    0.000    0.000    0.000 t.py:2(<genexpr>)

How to read stat

일단, docs.python.org 에 있는 내용을 그냥 가져오겠다. 왼쪽부터 순서대로 ncalls/tottime/percall/cumtime/percall 가 있다.

  • ncalls: 호출 횟수
  • tottime: 해당 함수에서 사용한 시간 - 내부에서 부른 다른 함수 호출 시간은 제외
  • percall: tottime / ncalls
  • cumtime: 함수 진입부터 나갈 때 까지의 시간 - 다른 함수 호출 시간도 포함
  • percall: cumtime / primitive calls

cumtime 의 경우 재귀함수에 대해서도 동작하는데 이 때문에 primitive calls 가 따로 존재한다. ncalls 에 숫자가 두개, a/b 처럼 나오는 경우 a가 actual calls, b가 primitive calls 다. primitive calls는 재귀 횟수를 무시한 호출횟수다. 예를 들어서,

def t(n=100):
    if n == 0:
        return n
    return n+t(n-1)
import profile
profile.run('print(t())')

이런 경우에는

5050
         104 function calls (4 primitive calls) in 0.010 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.010    0.010    0.010    0.010 :0(setprofile)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.000    0.000    0.010    0.010 profile:0(print(t()))
        0    0.000             0.000          profile:0(profiler)
    101/1    0.000    0.000    0.000    0.000 test_recursive.py:1(t)
    

이렇게 actual calls=101, primitive calls=1 이라는 결과가 나온다.

Command line

이렇게 꼭 코드 조각을 넣어야 하는게 귀찮을 수도 있다. 쓰던 코드를 고치지 않고 바로 프로파일링을 해보고 싶은데 말이지 … 그렇다면 그냥 커맨드라인에서 프로파일 옵션을 줄 수도 있다.test.py 라는 파일을 프로파일링 하고 싶다고 하자. 그러면,

python -m profile test.py

혹은, 결과를 파일로 얻고 싶다면

python -m profile -o test.prof test.py

이렇게 실행할 수 있다.

Analyze profiling data file

profile.run 혹은 커맨드라인 명령을 통하여 프로파일링 데이터가 저장된 파일을 얻었다면 pstat 모듈로 이를 읽을 수 있다.

  1. import pstats
  2. pstats.Stat 클래스 생성자에 파일 패스를 넘겨 스탯 객체를 얻는다
  3. 스탯 객체의 sort_stats, print_stats 등을 사용해서 스탯을 본다.

위에서 test.prof 를 만들었으니 이를 예로 들어보면 아래와 같이 볼 수 있다. 정렬에 대한 좀 더 자세한 설명은 여기서 보자.

import pstats
stat = pstats.Stats('test.prof')
stat.sort_stats('cumulative').print_stats(30)

Tue May 11 18:05:24 2010    test.prof

         131 function calls in 0.010 CPU seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.010    0.010 profile:0(execfile('test.py'))
        1    0.000    0.000    0.010    0.010 test.py:1(<module>)
        1    0.000    0.000    0.010    0.010 :0(execfile)
      122    0.010    0.000    0.010    0.000 test.py:2(<genexpr>)
        1    0.000    0.000    0.010    0.010 <string>:1(<module>)
        2    0.000    0.000    0.010    0.005 test.py:1(test)
        2    0.000    0.000    0.010    0.005 :0(sum)
        1    0.000    0.000    0.000    0.000 :0(setprofile)
        0    0.000             0.000          profile:0(profiler)

cProfile

cProfile은 profile과 거의 동일한 인터페이스를 가진 C-binding 이다. 위의 profile 에 대한 내용에서 profile→cProfile 로 바꾸면 모두 동작한다. 프로파일러의 몇몇 확장에서 차이를 보일 수 있으나, 그 부분은 여기서 다루지는 않는다. cProfile 쪽이 오버헤드가 더 작다고 한다.

Yappi

Yet Another Python Profiler

profile/cProfile은 스레드를 사용하는 프로그램은 기본적인 사용법만으로는 프로파일링 데이터를 얻어낼 수 없고, 오직 메인 스레드만을 프로파일링 하게 된다. 멀티스레드 프로그램을 프로파일링 하기 위해서는,

  • 각 스레드로부터 각각 프로파일링 데이터를 얻어낸 후 이를 합친다
  • threading.setprofile 에 적절한 프로파일링 함수(혹은 함수 객체)를 만들어 넘긴다

정도의 작업이 필요하다. 이게 귀찮으면 나름 간단한 인터페이스로 무장한 yappi 를 사용해 볼 수 있다.

Concept

  • yappi는 파이썬 인터프리터당 하나씩의 객체만 있다. 싱글톤이라고 봐도 무난할 듯 싶다.
  • 프로파일링 하고 싶은 부분이 시작되기 전에 yappi.start, 마치고 나서 yappi.stop 을 불러주면 된다.
  • start-stop 은 짝만 맞으면 여러번 할 수 있으므로 프로파일링 범위를 조절할 수 있다.
  • yappi.get_stats 를 부르면 스탯이 나온다. 숫자같은건 없으므로 그냥 '\n'.join(yappi.get_stats()) 를 찍어놓고 읽는게 편하다.
  • profile/cProfile 처럼 actual calls/primitive calls 구분은 안해준다

Install

그냥 소스코드를 받아서 python setup.py install 을 실행하면 된다. 디군은 계정 로컬로 설치하기 위해 –prefix 옵션을 주었다.

svn checkout http://yappi.googlecode.com/svn/trunk/ yappi-read-only
cd yappi-read-only
python setup.py install --prefix=~/works

물론 이렇게 로컬에 설치하는 경우에는 prefix/lib/python2.x/site-packages 를 PYTHONPATH 에 잡아주어야 한다.

How to write code

긴 설명보다 그냥 샘플 코드가 나을 듯.

import yappi
from threading import Thread

yappi.start()
def test(n=100):
    return sum(x for x in xrange(n))
test(10000)
yappi.stop()

def recursive(n=100):
    if n == 0:
        return n
    return n+recursive(n-1)
yappi.start()
recursive(100)
yappi.stop()

yappi.start()
class TestThread(Thread):
    def __init__(self, n=100):
        Thread.__init__(self)
        self.n = n

    def run(self):
        self.output = sum(x for x in xrange(self.n))

t_list = []
for t_n in xrange(10):
    t = TestThread(100000)
    t_list.append(t)
    t.start()

for t in t_list:
    t.join()
    print t.output
yappi.stop()

print('\n'.join(yappi.get_stats()))
4999950000
4999950000
4999950000
4999950000
4999950000
4999950000
4999950000
4999950000
4999950000
4999950000




name                                 #n       tsub       ttot       tavg
test_yappi.py.<genexpr>:25           1000010  28.059563  28.059563  0.000028   
test_yappi.py.<genexpr>:6            10001    0.036889   0.036889   0.000004   
test_yappi.py.recursive:10           101      0.000000   0.000000   0.000000   
..lib/python2.6/threading.py._note:6 58       0.000134   0.000134   0.000002   
../python2.6/threading.py.__init__:5 40       0.000132   0.000132   0.000003   
..ython2.6/threading.py._is_owned:22 24       0.317279   0.317395   0.013225   
..ython2.6/threading.py.Condition:17 20       0.000141   0.000587   0.000029   
..n2.6/threading.py.currentThread:80 20       0.000109   0.000148   0.000007   
..python2.6/threading.py.__init__:18 20       0.000389   0.000446   0.000022   
..ib/python2.6/threading.py.isSet:37 20       0.000043   0.000043   0.000002   
..n2.6/threading.py._release_save:21 14       0.000061   0.000093   0.000007   
..6/threading.py._acquire_restore:21 14       0.000075   0.000149   0.000011   
..lib/python2.6/threading.py.wait:23 14       0.000440   4.492487   0.320892   
..ib/python2.6/threading.py.start:46 10       0.000227   1.464204   0.146420   
..python2.6/threading.py._newname:40 10       0.000128   0.000128   0.000013   
test_yappi.py.run:24                 10       0.000034   1.980854   0.198085   
..ython2.6/threading.py.notifyAll:29 10       0.000099   0.000434   0.000043   
..python2.6/threading.py.__init__:36 10       0.000116   0.000540   0.000054   
..b/python2.6/threading.py.daemon:68 10       0.000028   0.000028   0.000003   
..ib/python2.6/threading.py.Event:35 10       0.000062   0.000602   0.000060   
..lib/python2.6/threading.py.wait:39 10       0.000207   1.463267   0.146327   
..hon2.6/threading.py._set_daemon:44 10       0.000089   0.000193   0.000019   
..lib/python2.6/threading.py.join:62 10       0.000234   3.029895   0.302989   
..b/python2.6/threading.py.notify:27 10       0.000137   0.000306   0.000031   
..b/python2.6/threading.py.__stop:58 10       0.000172   0.000670   0.000067   
..python2.6/threading.py.__init__:42 10       0.000295   0.001501   0.000150   
test_yappi.py.__init__:20            10       0.000095   0.001596   0.000160   
..n2.6/dist-packages/yappi.py.stop:4 3        0.000000   0.000000   0.000000   
..ython2.6/threading.py.setprofile:8 3        0.000008   0.000008   0.000003   
test_yappi.py.test:5                 1        0.000013   0.066473   0.066473   
test_yappi.py.TestThread:19          1        0.000004   0.000004   0.000004   


name           tid    fname                                scnt     ttot
_MainThread    1404.. ..ython2.6/threading.py.setprofile:8 18       15.052343  
TestThread     1404.. ..lib/python2.6/threading.py._note:6 41       3.035096   
TestThread     1404.. ..lib/python2.6/threading.py._note:6 44       3.392308   
TestThread     1404.. ..lib/python2.6/threading.py._note:6 39       2.893798   
TestThread     1404.. ..lib/python2.6/threading.py._note:6 45       2.980898   
TestThread     1404.. ..lib/python2.6/threading.py._note:6 32       2.609834   
TestThread     1404.. ..lib/python2.6/threading.py._note:6 44       3.146486   
TestThread     1404.. ..lib/python2.6/threading.py._note:6 33       2.057063   
TestThread     1404.. ..lib/python2.6/threading.py._note:6 28       3.148883   
TestThread     1404.. ..lib/python2.6/threading.py._note:6 38       3.028107   
TestThread     1404.. ..lib/python2.6/threading.py._note:6 42       3.748974   


status     tstart                     fcnt     tcnt     mem(bytes)
stopped    Tue May 11 19:23:22 2010   81       11       105408   

real	0m4.635s
user	0m0.720s
sys	0m3.150s

Profile/cProfile on Multithread program

  • 위에서 언급한 스레드마다 profile 을 따로 뽑아보는 접근을 해보자
  • profile.run, cProfile.run 대신 profile.runctx, cProfile.runctx 를 사용할 수 있다
  • ctx버전은 실행할 코드조각에 환경 - globasl(), locals() - 을 추가로 넘긴다

import cProfile
class ThreadToProfile(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        
    def run_profile(self):
        """ DO WHATEVER YOU WANT """
        pass
        
    def run(self):
        cProfile.run("self.run_profile()", globals(), locals())

이 경우 stdout 으로 각 스레드의 프로파일 결과가 나오게 된다. 이를 합치기 위해서는 각각 다른 이름의 파일(이름이 같으면 broken pipe, 혹은 덮어쓰기)로 만들어서 pstats 으로 하나를 열고, 나머지 파일들을 Stat.add 메소드로 더하면 된다.

Links

[출처 : http://terzeron.net/wp/?p=770]


다음의 예제는 python에 기본 내장된 프로파일러(profiler)인 hotshot을 이용하여 GNU prof와 비슷하게 프로파일링하는 것을 시연해 본 것이다.

01 #!/usr/bin/env python
02 # -*- coding: utf-8 -*-
03 # vim: set fileencoding=utf-8 :
04  
05 import hotshot, hotshot.stats
06  
07 def test_func2(i):
08     result = * 10
09     return result
10  
11 def test_func1(i):
12     test_func2(i)
13     result = 1 * i
14     return result
15  
16 profile_filename = "prof.result"
17 prof = hotshot.Profile(profile_filename)
18 prof.start()
19  
20 sum = 0
21 for in range(10000):
22     sum = sum + i
23     test_func1(i)
24 print sum
25  
26 prof.stop()
27 prof.close()
28 stats = hotshot.stats.load(profile_filename)
29 stats.strip_dirs()
30 stats.sort_stats('time''calls')
31 stats.print_stats()

이 스크립트의 실행 결과는 다음과 같다.

49995000
20000 function calls in 0.012 CPU seconds

Ordered by: internal time, call count

ncalls tottime percall cumtime percall filename:lineno(function)
10000 0.008 0.000 0.012 0.000 profile_example.py:11(test_func1)
10000 0.004 0.000 0.004 0.000 profile_example.py:7(test_func2)
0 0.000 0.000 profile:0(profiler)

첫번째 줄은 스크립트가 수행한 결과인 1부터 10000까지의 합을 계산한 것이다. 나머지 부분이 프로파일러가 출력한 통계치인데 다음과 같이 해석할 수 있다.

1) 총 2만 개의 함수 호출이 있었고, 0.012 초가 소요되었다.
2) 수행 시간과 호출 횟수를 기준으로 정렬되었다.
3) profile_example.py의 test_func1() 함수는 1만 번 호출되었고 총 수행 시간은 0.008초인데, 한 번 호출은 0.008/10000=0.000초이다. test_func1()이 호출한 하위 함수들까지 포함한 누적 수행 시간은 0.012초이다.
4) 같은 스크립트의 test_func2() 함수는 1만 번 호출되었고 총 수행 시간은 0.004초인데, 하위 함수들까지 포함한 누적 수행 시간은 0.004초이다.

[출처 : http://dududu.tistory.com/entry/파이썬-자연어처리-라이브러리]


영어 문법 데이타 찾는 뻘짓하다가 아는 분에게 물어보니 파이썬으로도 구현된 툴이 있을 거라고 하더군요. 검색하니까 바로 나오네요.


http://nltk.sourceforge.net/

그리고 inflector를 이용하면 영어 명사를 복수형으로 바꿀 수 있습니다. 아래 링크는 파이썬용이지만 다른 언어용 inflector도 있습니다.

http://www.bermi.org/inflector/download
[출처 : http://dududu.tistory.com/entry/파이썬에서-실행시간을-측정하는-코드]


아래는 파이썬의 실행시간을 측정하는 코드이다.
timing 모듈을 임포트하여 사용한다.
본래의 링크는http://home.paran.com/johnsonj/etc/Efficient%20String%20Concatenation%20in%20Python.htm

from cStringIO import StringIO
import timing, commands, os
from sys import argv

# .....
# 여기에 메쏘드를 정의한다
# .....

def ps_stat():
global process_size
ps = commands.getoutput('ps -up ' + `pid`)
process_size = ps.split()[15]

def call_method(num):
global process_size
timing.start()
z = eval('method' + str(num))()
timing.finish()
print "method", num
print "time", float(timing.micro()) / 1000000
print "output size ", len(z) / 1024, "kb"
print "process size", process_size, "kb"
print

loop_count = 500000
pid = os.getpid()

call_method(argv[1])

[출처 : http://creaplz.tistory.com/57]


1. 파일쓰기
  - open(file) 내장 함수로 파일 객체를 얻음
  - 얻어진 파일 객체서 자료를 읽고 씀
  - close로 객체 사용을 종료(생략 가능)
>>> s = '''
Its power: Python developers typically report
they are able to develop application in a half
to a tenth the amount of time it takes them to do
the same work in such langueges as C.
'''
>>> f = file('t.txt', 'w')
>>> f.write(s)
>>> f.close()


2. 파일 읽기

>>> f = file('t.txt') # 두 번째 인수 생략 시, 읽기 모드로 동작
>>> s = f.read()
>>> print s

Its power: Python developers typically report
they are able to develop application in a half
to a tenth the amount of time it takes them to do
the same work in such langueges as C.

3. 라인 단위로 파일 읽기
  - 파일 객체의 반복자(Iterator) 이용하기(가장 효과적인 방법)

>>> f = open('t.txt')
>>> for line in f:
 print line,

  - readline : 한 번에 한 줄씩 읽는다.

>>> f = open('t.txt')
>>> line = f.readline()
>>> while line:
 print line, # line 자체에 \n이 포함되어 있어 콤마(,)를 사용
 line = f.readline()

  - readlines : 파일 전체를 라인 단위로 끊어서 리스트에 저장한다.

>>> f = open('t.txt')
>>> for line in f.readlines():
 print line,

  - xreadlines : readlines와 유사하지만 파일 전체를 한꺼번에 읽지는 않고, 필요할 때만 읽어서 공급한다. 큰 파일을 for 문으로 라인 단위로 읽을 때 편리하다.

>>> f = open('t.txt')
>>> for line in f.xreadlines():
 print line,

4. 라인 단위로 파일 쓰기

>>> lines = ['first line\n', 'second line\n', 'third line\n']
>>> f = open('t1.txt', 'w')
>>> f.writelines(lines)
>>>
>>> lines = ['first line', 'second line', 'third line']
>>> f = open('t1.txt', 'w')
>>> f.write('\n'.join(lines))

※ 단어의 수 구하기

>>> n = len(open('t.txt').read().split())
>>> print n
35

※ 라인의 수 구하기

>>> len(open('t.txt').readlines())
5
>>> open('t.txt').read().count('\n')
5

※ 문자의 수 구하기

>>> f = open('t.txt')
>>> len(f.read()) # 줄바꾸기 : '\012'
182
>>> os.path.getsize('t.txt') # 줄바꾸기 : '\015\012'
187L

5. 파일에서 원하는 만큼의 문자 읽기

>>> f = open('t.txt')
>>> f.read(10) # 10바이트 만큼만 읽기
'\nIts power'
>>> f.read(10)
': Python d'

6. 파일 처리 모드
  - 'r' : 읽기 전용
  - 'w' : 쓰기 전용
  - 'a' : 파일 끝에 추가(쓰기 전용)
  - 'r+' : 읽고 쓰기
  - 'w+' : 읽고 쓰기(기존 파일 삭제)
  - 'a+' : 파일 끝에 추가(읽기도 가능)
  - 'rb' : 이진 파일 읽기 전용
  - 'wb' : 이진 파일 쓰기 전용
  - 'ab' : 이진 파일 끝에 추가(쓰기 전용)
  - 'rb+' : 이진 파일 읽고 쓰기
  - 'wb+' : 이진 파일 읽고 쓰기(기존 파일 삭제)
  - 'ab+' : 이진 파일 끝에 추가(읽기도 가능)
※ 플랫폼에 의존하지 않는 코드를 작성하려 한다면 이진 파일을 다룰 때 b 플래그를 사용하는 것이 좋다.

7. 임의 접근 파일
  - seek(n) : 파일의 n번째 바이트로 이동
  - seek(n, 1) : 현재 위치에서 n바이트 이동(n이 양수이면 뒤쪽으로, 음수이면 앞쪽으로 이동)
  - seek(n, 2) : 맨 마지막에서 n바이트 이동(n은 보통 음수)
  - tell() : 현재의 파일 포인터 위치를 돌려줌

>>> fn = 't.txt'
>>> f = open(fn, 'w+')
>>> s = '0123456789abcdef'
>>> f.write(s)
>>> f.seek(5)
>>> print f.tell() # 현재 위치를 돌려줌
5
>>> print f.read(1) # 1바이트 읽기
5
>>> f.seek(-3, 2) # 끝부터 앞으로 3번째 지점
>>> print f.tell()
13
>>> print f.read(1)
d

8. 파일 객체 속성들
  1) 기본 파일 메쏘드
    - file.close() : 파일을 닫는다. 더 이상 입ㆍ출력할 수 없게 된다.
    - file.read([size]) : 원하는 바이트 수만큼 파일에서 읽어 온다. 인수를 지정하지 않으면 전체 파일을 읽어 온다.
    - file.readline([size]) : 라인 하나를 읽어 들인다. size가 지정되면 읽을 수 있는 최대 바이트 수가 된다.
    - file.readlines() : 전체 라인을 readline()을 이용하여 읽어 들인 라인을 리스트에 넣어서 리턴한다.
    - file.write(str) : 문자열 str을 파일에 쓴다.
    - file.writelines(list) : 문자열 리스트를 파일에 쓴다. 줄바꾸기가 자동으로 삽입되지는 않는다.
    - file.seek(offset[, whence]) : whence의 기본 값은 0이다. 0이면 시작 기준, 1이면 현재 위치 기준, 2이면 끝 기준에서 offset만큼 떨어진 위치에 파일 포인터를 위치시킨다.
    - file.tell() : 파일의 현재 위치를 리턴한다.
  2) 기타의 파일 메쏘드
    - file.flush() : 버퍼가 다 채워지지 않았어도 내부 버퍼의 내용을 파일에 보낸다.
    - file.fileno() : file 객체의 파일 기술자(File Descriptor)(정수)를 리턴한다.
    - file.isatty() : 만일 file 객체가 tty와 같은 장치이면 1이면 0을 리턴
    - file.truncate([size]) : 파일 크기를 지정된 크기로 잘라 버림. 인수를 주지 않으면 현재 위치에서 자른다.
  3) 파일 객체 속성
    - file.closed : file이 close 되었으면 1 아니면 0
    - file.mode : 파일이 오픈된 모드
    - file.name : open()할 때 사용된 파일 이름
    - file.softspace : 1이면 print문을 사용할 때 값 출력 사이에 자동적으로 스페이스가 출력됨. 0이면 스페이스가 자동으로 삽입되지 않음

9. 파일 입ㆍ출력 예제

## 지정한 파일의 특정 문자열을 다른 문자열로 변환
# @file repalce.py

import sys  # argv를 위해서 사용
import re   # 정규식 처리 모듈, subn을 위해서 사용

def replace(fName, srcStr, desStr):
    f = open(fName)
    txt = f.read()
    txt = re.subn(srcStr, desStr, txt)[0]
    return txt

if __name__ == '__main__':
    if len(sys.argv) != 4:
        print '''Usage : replace fileName srcStr desStr'''
        sys.exit()
    print replace(sys.argv[1], sys.argv[2], sys.argv[3])


10. 표준 입ㆍ출력 방향 전환
  1) 표준 출력을 파일로 저장하기
    - 출력 방향 전환하기

import sys

f = open('t.txt', 'w')
stdout = sys.stdout # 표준 출력 파일 저장해 두기
sys.stdout = f  # 파일 객체로 변경
print 'Sample output'
print 'Good'
print 'Good'
f.close()
sys.stdout = stdout # 필요하면 복구

    - print 문을 직접 이용하기

>>> import sys
>>> print >> sys.stderr, 'Warning: action filed not supplied'
Warning: action filed not supplied
>>> f = open('t.txt', 'w')
>>> print >> f, 'spam string'
>>> f.close()


  2) 표준 출력을 문자열로 저장하기

import sys
import StringIO

stdout = sys.stdout # 표준 출력 파일 저장해 두기
sys.stdout = f = StringIO.StringIO()    # 출력 파일 방향 전환

print 'Sample output'
print 'Good'
print 'Good'

sys.stdout = stdout # 표준 출력 복구
s = f.getvalue()    # 내부 문자열 가져오기

print 'Done-----'
print s

  3) 문자열을 파일 객체처럼 읽어 내기

try:
    import cStringIO    # 빠른 처리를 원한다면 C 버전 모듈인 cStringIO 사용
    StringIO = cStringIO
except:
    import StringIO
s = '''
Python is a cool little language.
It is wall designed, compact, easy to learn and fun to program in.
'''
f = StringIO.StringIO(s)    # 문자열 객체에서 파일 객체 얻어내기
print f.read().upper()  # 대문자로 변환


11. 지속 모듈 : 프로그램이 종료되고 나서도 존재하게 하고, 그 후에 다시 그 데이터를 프로그램에서 사용
  1) 종류
    - DBM 관련 모듈
    - pickle 모듈
    - marshal 모듈
    - shelve 모듈
  2) DBM 파일 관련 모듈 사용하기
    - anydbm, dbm, gdbm, dbhash, dumbdbm 등
    - anydbm 모듈 : 사용 가능한 DBM 호환 가능 최적의 모듈을 찾아 준다.
    - 키에 의한 참조(인덱싱)로 파일에서 자료를 읽어 오고, 인덱싱으로 치환하는 것으로 파일에 자료를 저장
    - 키와 값은 반드시 문자열이어야 한다.

>>> import anydbm
>>> f = anydbm.open('music', 'c') # 'c'(create)는 파일이 없으면 생성, 있으면 읽기로 오픈
>>> f['flute'] = 'wood wind' # 인덱싱으로 치환
>>> f['violin'] = 'string'
>>> f['piano'] = 'keyboard'
>>> f.keys() # keys() 메쏘드
['flute', 'violin', 'piano']
>>> f.values()
['wood wind', 'string', 'keyboard']
>>> f.items()
[('flute', 'wood wind'), ('violin', 'string'), ('piano', 'keyboard')]
>>> len(f) # 레코드 수
3
>>> 'oboe' in f # 멤버십 테스트
False
>>> f['flute'] # 인덱싱으로 값 읽어 오기
'wood wind'
>>> f['violin']
'string'
>>> f.close() # 파일 닫기
>>> ========================== RESTART ==========================
>>> import anydbm
>>> f = anydbm.open('music', 'c') # 'music' 파일 열기
>>> f.keys() # 키 목록 얻기
['flute', 'violin', 'piano']
>>> for k in f: # 전체 내용 출력
 print k, f[k]

flute wood wind
violin string
piano keyboard

>>> f['oboe'] = 'wood wind' # 내용 추가
>>> f['piano'] = 'keyboard instrument' # 내용 변경
>>> del f['violin'] # 내용 삭제
>>> for k in f: # 다시 전체 내용 출력
 print k, f[k]

flute wood wind
piano keyboard instrument
oboe wood wind


  3) 피클링
    - 모든 객체 저장
    - 재귀적 관계도 모두 처리
    - import pickle(또는 cPickle) : 모듈 import
      pickle.dump(출력할 객체, 파일 객체) : 파일로 객체 출력
      object = pickle.load(파일 객체) : 파일에서 객체를 읽어들임
      s = pickle.dumps(출력할 객체) : 문자열로 객체 출력
      object = pickle.loads(s) : 문자열에서 객체를 읽어들임
    - 장점 : 디버깅을 쉽게하고 문제가 생겼을 때 일반 텍스트 에디터로 복구를 쉽게할 수 있다.
    - 단점 : 파일 크기도 크고 또한 처리 속도도 느리다.
    ※ cPickle 모듈은 pickle 모듈과 같은 인터페이스를 가지고 있지만 약 1000배 빨리 수행되도록 설계되었다.

## pickle sample

# @file pickleSample1.py
try:
    import cPickle
    pickle = cPickle
except:
    import pickle

phone = {'tom': 4358382, 'jack': 9465215, 'jim': 6851325, 'Joseph': 6584321}
List = ['string', 1234, 0.2345]
Tuple = (phone, List)   # 리스트, 튜플, 사전의 복합 객체

f = open('t2.txt', 'w') # 파일 객체를 얻는다.

pickle.dump(Tuple, f)   # 파일로 복합 객체 출력(pickling)
f.close()

f = open('t2.txt')

x, y = pickle.load(f)   # 파일에서 읽어 오기(unpickling)
print x # x는 사전
print y # y는 리스트


# @file pickleSample2.py
try:
    import cPickle
    pickle = cPickle
except:
    import pickle
class Simple:   # 가장 단순한 클래스를 정의
    pass

s = Simple()    # 인스턴스 객체 생성
s.count = 10    # 인스턴스 이름 공간에 변수 생성

f = open('t3.txt', 'w') # 인스턴스 저장
pickle.dump(s, f, 1)    # bin=1 : 이진 모드로 저장
f.close()

f = open('t3.txt')
t = pickle.load(f)  # 인스턴스 가져오기

print t.count


[출처 : http://creaplz.tistory.com/51]


1. 객체의 복사 : 같은 값을 가지는 객체를 하나 혹은 그 이상 만드는 것
  1) copy 모듈을 이용한 객체 복사
    - 얕은 복사(Shallow Copy) : 복합 객체를 별도로 생성하되 내용은 원래의 레퍼런스로 채운다.
>>> import copy
>>> a = [1, 2, 3]
>>> b = [4, 5, a]
>>> x = [a, b, 100]
>>> y = copy.copy(x)

    - 깊은 복사(Deep Copy) : 복합 객체를 생성하고 내용을 재귀적(Recursive)으로 복사한다.
>>> import copy
>>> a = [1, 2, 3]
>>> b = [4, 5, a]
>>> x = [a, b, 100]
>>> y = copy.deepcopy(x)


2. 형 변환
  1) 수치 형 변환
    - 정수형 변환 : int()
      ※ 실수→정수 : int(), round(), floor(), ceil()
    - 실수, 롱형으로의 형 변환 : float(), long()
    - 복소수로의 형 변환 : complex()
  2) 시퀀스 자료형 변환
    - 리스트로 변환 : list()
    - 튜플로 변환 : tuple()

>>> t = (1, 2, 3, 4)
>>> l = [5, 6, 7, 8]
>>> s = 'abcd'
>>> 
>>> print list(t), list(s)
[1, 2, 3, 4] ['a', 'b', 'c', 'd']
>>> print tuple(l), tuple(s)
(5, 6, 7, 8) ('a', 'b', 'c', 'd')

  3) 문자열로의 형 변환
    - 비형식적인 문자열로 변환 : str()
    - 형식적인 문자열로 변환 : repr()
    - `obj` : repr(obj)와 동일
    ※ 객체 ↔ 문자열 : repr(str은 완벽한 변환 안됨), eval 사용

>>> L = ['파란 하늘', 'blue sky', 1, 1234L, 1/3.0]
>>> for s in L:
 print 's', s
 print 'str(s)', str(s)
 print 'repr(s)', repr(s)
 print '\'s\'', `s`
 print


s 파란 하늘
str(s) 파란 하늘
repr(s) '\xc6\xc4\xb6\xf5 \xc7\xcf\xb4\xc3'
's' '\xc6\xc4\xb6\xf5 \xc7\xcf\xb4\xc3'

s blue sky
str(s) blue sky
repr(s) 'blue sky'
's' 'blue sky'

s 1
str(s) 1
repr(s) 1
's' 1

s 1234
str(s) 1234
repr(s) 1234L
's' 1234L

s 0.333333333333
str(s) 0.333333333333
repr(s) 0.33333333333333331
's' 0.33333333333333331

  4) 문자열 요소를 가지는 리스트나 튜플을 문자열로 변환

>>> import string
>>> s = 'Python is the first language'
>>> L = s.split()
>>> L
['Python', 'is', 'the', 'first', 'language']
>>> ' '.join(L)
'Python is the first language'
  5) 리스트, 튜플과 사전의 변환
    - 사전에서 리스트로 변환
>>> d = {1: 'one', 2: 'two', 3: 'three'}
>>> d.keys()
[1, 2, 3]
>>> d.values()
['one', 'two', 'three']
>>> d.items()
[(1, 'one'), (2, 'two'), (3, 'three')]
    - 리스트에서 사전으로 변환
>>> keys = ['a', 'b', 'c', 'd']
>>> values = [1, 2, 3, 4]
>>> L = zip(keys, values)
>>> L
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> dict(L)
{'a': 1, 'c': 3, 'b': 2, 'd': 4}

  6) 문자 변환
>>> chr(97) # 아스키 코드 → 문자
'a'
>>> ord('a') # 문자 → 아스키 코드
97
  7) 임의의 진수를 10진수로 변환
>>> int('64', 16) # 16진수 '64'를 10진수로
100
>>> int('144', 8) # 8진수 '144'를 10진수로
100
>>> int('101111', 2) # 2진수 '101111'을 10진수로
47
>>> int('14', 5) # 5진수 '14'를 10진수로
9
  8) 10진수를 임의의 진수로 변환
    - 10진수에서 8, 16진수로
>>> hex(100) # 10진수 100을 16진수 문자열로 변환
'0x64'
>>> oct(100) # 10진수 100을 8진수 문자열로 변환
'0144'

    - 10 진수에서 2진수로

## 10진수 → 2진수

# @file int2bin1.py
octtab = {'0': '000', '1': '001', '2': '010', '3': '011',
    '4': '100', '5': '101', '6': '110', '7': '111'}

def bin1(d, width=0):
    "integer to binary(string)"
    s = "%o" % d
    b = ''
    for el in s:
        b += octtab[el]
    if width > 0:
        if len(s) > width:
            return b[:width]
        b = b.zfill(width)
    return b

print bin1(23, 7)   # 0010111

# @file int2bin2.py
def bin2(n, width=0):
    result = []
    while 1:
        result[:0] = [str(n&1)]
        n >>= 1
        if not n:
            break
    results = ''.join(result)
    if not width:
        width = len(results)
    return results.zfill(width)[:width]

print bin2(23, 7) 
# 0010111

    - 10진수에서 임의의 진수로

## 10진수 → 임의의 진수
#  @param n 10진수
#  @param base 변환할 진수
#  @param width 출력 문자열 폭. 0이면 기본 값

def int2digit(n, base, width=0):
    res = ''
    while n > 0:
        n, r = divmod(n, base)
        if r > 9:
            r = chr(ord('a')+r-10)
        res += str(r)
    if not res:
        res = '0'
    if not width:
        width = len(res)
    return res.zfill(width)[:width]

print int2digit(70, 5)       # 240
print int2digit(70, 12)     # 5a
print int2digit(70, 15)     # 4a
print int2digit(70, 16)     # 46
print int2digit(70, 2, 8)   # 01000110

  9) 정수를 콤마가 있는 문자열로 변환

>>> import locale
>>> locale.setlocale(locale.LC_ALL, "") # 사용자 기본 환경(국가 혹은 언어)으로 설정
'Korean_Korea.949'
>>> print locale.format("%d", 10030405, 1)
10,030,405

+ Recent posts