2008-10-22 29 views
13

Tôi muốn thực hiện một số lọc cơ bản trên tệp. Đọc nó, xử lý, viết lại.Mở tệp, đọc, xử lý và viết lại - phương pháp ngắn nhất trong Python

Tôi không tìm kiếm "chơi gôn", nhưng muốn có phương pháp đơn giản và thanh lịch nhất để đạt được điều này. Tôi đã đưa ra:

from __future__ import with_statement 

filename = "..." # or sys.argv... 

with open(filename) as f: 
    new_txt = # ...some translation of f.read() 

open(filename, 'w').write(new_txt) 

Tuyên bố with làm cho mọi việc ngắn hơn vì tôi không phải mở và đóng tệp một cách rõ ràng.

Bất kỳ ý tưởng nào khác?

Trả lời

25

Trên thực tế một cách dễ dàng hơn bằng fileinput là sử dụng các tham số inplace:

import fileinput 
for line in fileinput.input (filenameToProcess, inplace=1): 
    process (line) 

Nếu bạn sử dụng tham số inplace, nó sẽ chuyển hướng stdout vào tệp của bạn, để nếu bạn in, nó sẽ ghi lại tệp của bạn.

Ví dụ này cho biết thêm số dòng vào tập tin của bạn:

import fileinput 

for line in fileinput.input ("b.txt",inplace=1): 
    print "%d: %s" % (fileinput.lineno(),line), 
+0

Rất tốt, cảm ơn bạn đã chỉ ra tùy chọn này. Bạn cũng có thể sử dụng hàm filelineno() từ fileinput để tự động có số dòng, mà không tự tính nó. –

+1

Ồ, và bạn quên dấu phẩy sau khi in - mã bổ sung thêm dòng mới :-) –

+0

Cảm ơn bạn đã bắt được - Tôi đã thay đổi ví dụ. – Hortitude

3

Điều này dường như làm việc:

with open(filename, "r+") as f: 
    new_txt = process(f.read()) 
    f.truncate(0) 
    f.write(new_txt) 
+0

Chỉ hoạt động khi gọi 'f.seek (0)' sau 'f.truncate (0)', nếu không tệp mới bắt đầu bằng 11 byte không (Python 2.7.3 trên Linux). – scai

4

tôi sẽ đi cho tao nhã một cách khác nhau: thực hiện tập đọc và lọc của bạn hoạt động như máy phát điện, Bạn sẽ viết thêm dòng mã, nhưng nó sẽ có nhiều mã linh hoạt, bảo trì và hiệu suất.

Xem David M. Beazley Generator Tricks for Systems Programmers, điều thực sự quan trọng đối với bất kỳ ai viết loại mã này để đọc.

+0

Liên kết tuyệt vời - cảm ơn bạn! Tôi hơi lo ngại về sự gia tăng khó khăn trong việc gỡ lỗi đường ống, nhưng sức mạnh là không thể phủ nhận. –

+1

Phát triển theo hướng thử nghiệm là bạn của bạn. –

2

Nếu bạn đang tìm kiếm tương đương với python của "perl -pi", đây là một khá tốt một:

 
import fileinput 
for line in fileinput.input(): 
    # process line 

Xem http://www.python.org/doc/2.5.2/lib/module-fileinput.html để biết thêm.

Xong Bằng cách này, bạn sẽ sử dụng kịch bản python của bạn trong một ống để tạo ra các tập tin mới:

 
$ myscript.py infile.txt > outfile.txt 
+0

Nó không thực sự giúp tôi mặc dù, vì tôi muốn viết lại cho cùng một tập tin. Và chuyển hướng sẽ không hoạt động theo cách này cho cùng một tệp –

1

Để làm điều đó theo một cách mà sẽ không eat your data nếu bạn sụp đổ ở giữa:

from twisted.python.filepath import FilePath 
p = FilePath(filename) 
p.setContent(process(p.getContent())) 
0

tôi xấu xí (nhưng ngắn như đã nêu trong câu hỏi) giải pháp với generator expressions;

# Some setup first 
file('test.txt', 'w').write('\n'.join('%05d' % i for i in range(100))) 


# This is the filter function 
def f(i): 
    return i % 3 


# This is the main part 
file('test2.txt', 'w').write('\n'.join(str(f(int(l))) for l in file('test.txt', 'r').readlines())) 


# And a wrapper for sanity 
def filter_file(infile, outfile, filter_function) 
    outfile.write('\n'.join(filter_function(l) for l in infile.readlines())) 
Các vấn đề liên quan