2009-09-16 38 views
26

Giả sử chúng tôi muốn thực hiện tương đương với file_get_content của PHP.cách lấy nội dung của tệp ascii nhỏ trong python?

Phương pháp hay nhất là gì? (thanh lịch và đáng tin cậy)

Dưới đây là một số đề xuất, chúng có chính xác không?

sử dụng with tuyên bố:

def file_get_contents(filename): 
    with file(filename) as f: 
     s = f.read() 
    return s 

đang sử dụng tiêu chuẩn open() an toàn không?

def file_get_contents(filename): 
    return open(filename).read() 

Điều gì sẽ xảy ra với bộ mô tả tệp trong một trong hai giải pháp?

Trả lời

39

Trong việc thực hiện hiện tại của CPython, cả hai sẽ thường đóng ngay lập tức tệp. Tuy nhiên, Python ngôn ngữ không đảm bảo cho ngôn ngữ thứ hai - tệp cuối cùng sẽ bị đóng, nhưng finaliser có thể không được gọi cho đến chu kỳ gc tiếp theo. Các triển khai như Jython và IronPython sẽ hoạt động như thế này, vì vậy thực hành tốt là đóng các tệp của bạn một cách rõ ràng.

Tôi muốn sử dụng giải pháp đầu tiên là phương pháp hay nhất, mặc dù open thường được ưu tiên là file. Lưu ý rằng bạn có thể rút ngắn nó một chút tuy nhiên nếu bạn thích ngắn gọn của ví dụ thứ hai:

def file_get_contents(filename): 
    with open(filename) as f: 
     return f.read() 

Các __exit__ phần của người quản lý bối cảnh sẽ thực hiện khi bạn rời khỏi cơ thể cho bất kỳ lý do, trong đó có trường hợp ngoại lệ và trở về từ hàm - không cần sử dụng biến trung gian.

+1

từ PEP 343: http://www.python.org/dev/peps/pep-0343 Lưu ý rằng chúng tôi không đảm bảo rằng điều khoản cuối cùng được thực thi ngay lập tức sau khi đối tượng máy phát điện trở nên không được sử dụng, mặc dù đây là làm thế nào nó sẽ làm việc trong CPython. Điều này tương tự như các tệp đóng tự động: trong khi việc triển khai tính tham chiếu như CPython deallocates một đối tượng ngay khi tham chiếu cuối cùng nó biến mất, việc triển khai sử dụng các thuật toán GC khác không thực hiện cùng một bảo đảm. Điều này áp dụng cho Jython, IronPython và có thể là Python chạy trên Parrot. – kriss

+0

@kriss: Lưu ý rằng điều đó không mâu thuẫn với tuyên bố về việc chạy '__exit__' khi rời khỏi cơ thể - nó chỉ chi tiết những gì xảy ra nếu bạn ** không ** thoát khỏi cơ thể bằng cách tạo một trình phát bị treo trong trình quản lý ngữ cảnh, và làm thế nào python sẽ buộc nó để lại bằng cách nâng cao một ngoại lệ. – Brian

2

with sẽ đảm bảo rằng tệp được đóng khi chặn.

Trong ví dụ thứ hai của bạn, xử lý tệp có thể vẫn mở (Python không đảm bảo rằng nó được đóng hoặc khi bạn không làm điều đó một cách rõ ràng).

+4

Không hẳn. Trên CPython, tệp được đóng ngay sau khi bộ mô tả tệp vượt quá phạm vi - chắc chắn là khi hàm trả về. (Tôi đã kiểm tra nguồn Python, vì thời điểm này xuất hiện ở nơi khác gần đây.) Trên IronPython và Jython, tệp sẽ bị đóng khi đối tượng tệp được thu thập rác, nhưng không đảm bảo khi nào sẽ xảy ra. –

+0

Nếu bạn không sử dụng 'with', tệp sẽ bị đóng ngay cả trong trường hợp ngoại lệ? –

+1

@Hank Gay: nếu bạn không có 'with' thì không có sự bảo đảm nào - bộ mô tả tập tin OS có thể được mở. –

1
import os 

def file_get_contents(filename): 
    if os.path.exists(filename): 
    fp = open(filename, "r") 
    content = fp.read() 
    fp.close() 
    return content 

Trường hợp này sẽ trả về Không nếu tệp không tồn tại và trình mô tả tệp sẽ bị đóng trước khi chúng tôi thoát khỏi hàm.

+4

Điều này bỏ lỡ điểm sử dụng 'with' - mã này có cùng điểm yếu như' new/delete' rõ ràng trong mã C++ - trong trường hợp có bất kỳ ngoại lệ can thiệp nào trước mã dọn dẹp, việc dọn dẹp không xảy ra. Trên Python trước đó, người ta có thể bọc ví dụ này trong 'try/catch/finally', nhưng những đứa trẻ thú vị đều sử dụng' with'. – PaulMcG

+0

Điều này bỏ lỡ điểm của câu hỏi về độ tin cậy. Nó thêm các tính năng không mong muốn (kiểm tra sự tồn tại của tập tin), và không đặc biệt thanh lịch (nhập mã os và chiều dài mã). – vaab

3

Sử dụng câu lệnh có thực sự là cách tốt nhất để là chắc chắn rằng tệp đó thực sự bị đóng.

Tùy theo trạng thái thu gom rác cho nhiệm vụ này có thể làm việc, nhưng trong trường hợp này, có một cách tốt đẹp để chắc chắn rằng trong mọi trường hợp, vì vậy ...

-1

Bạn cũng có thể sử dụng tính năng v3 Python:

>>> ''.join(open('htdocs/config.php', 'r').readlines()) 
"This is the first line of the file.\nSecond line of the file" 

đọc thêm ở đây http://docs.python.org/py3k/tutorial/inputoutput.html

+1

Hãy cẩn thận khi đăng bản sao và dán các câu trả lời chính xác/đúng nguyên văn cho nhiều câu hỏi, những câu hỏi này có xu hướng bị cộng đồng gắn cờ là "spam". Nếu bạn đang làm điều này thì nó thường có nghĩa là các câu hỏi là trùng lặp để đánh dấu chúng như vậy để thay thế. http://stackoverflow.com/questions/1433577 – Kev

Các vấn đề liên quan