Tóm lại: bạn không thể tránh 2 bản sao bằng cách sử dụng StringIO.
Một số giả thiết:
- Bạn đang sử dụng cStringIO, nếu không nó sẽ là ngớ ngẩn để tối ưu hóa này nhiều.
- Tốc độ và hiệu quả bộ nhớ không phải là sau. Nếu không, hãy xem giải pháp của Jakob Bowyer hoặc sử dụng biến thể bằng cách sử dụng
file.read(SOME_BYTE_COUNT)
nếu tệp của bạn là nhị phân.
- Bạn đã nêu điều này trong các nhận xét, nhưng để hoàn chỉnh: bạn thực sự muốn chỉnh sửa nội dung, không chỉ xem nội dung đó.
dài câu trả lời: Kể từ chuỗi python là không thay đổi và bộ đệm StringIO không phải là, một bản sao sẽ phải được thực hiện sớm hay muộn; nếu không bạn sẽ thay đổi một vật thể bất biến! Đối với những gì bạn muốn có thể, đối tượng StringIO sẽ cần phải có một phương thức chuyên dụng đọc trực tiếp từ một đối tượng tệp được đưa ra như một đối số. Không có phương pháp như vậy.
Bên ngoài của StringIO, có các giải pháp tránh sao chép bổ sung. Off đỉnh đầu của tôi, điều này sẽ đọc một tập tin trực tiếp vào một mảng byte sửa đổi, không sao chép thêm:
import numpy as np
a = np.fromfile("filename.ext", dtype="uint8")
Nó có thể là cồng kềnh để làm việc với, tùy thuộc vào việc sử dụng bạn có ý định, vì nó là một mảng của giá trị từ 0 đến 255, không phải là một mảng ký tự. Nhưng nó có chức năng tương đương với một đối tượng StringIO, và sử dụng np.fromstring
, np.tostring
, np.tofile
và ký hiệu cắt sẽ đưa bạn đến nơi bạn muốn. Bạn cũng có thể cần np.insert
, np.delete
và np.append
.
Tôi chắc rằng có các mô-đun khác sẽ thực hiện những việc tương tự.
timeit:
là bao nhiêu tất cả điều này thực sự vấn đề? Được rồi để xem. Tôi đã tạo một tệp 100MB, largefile.bin
. Sau đó, tôi đọc trong tập tin bằng cách sử dụng cả hai phương pháp và thay đổi byte đầu tiên.
$ python -m timeit -s "import numpy as np" "a = np.fromfile('largefile.bin', 'uint8'); a[0] = 1"
10 loops, best of 3: 132 msec per loop
$ python -m timeit -s "from cStringIO import StringIO" "a = StringIO(); a.write(open('largefile.bin').read()); a.seek(0); a.write('1')"
10 loops, best of 3: 203 msec per loop
Vì vậy, trong trường hợp của tôi, việc sử dụng StringIO chậm hơn 50% so với sử dụng gọn gàng.
Cuối cùng, để so sánh, chỉnh sửa các tập tin trực tiếp:
$ python -m timeit "a = open('largefile.bin', 'r+b'); a.seek(0); a.write('1')"
10000 loops, best of 3: 29.5 usec per loop
Vì vậy, đó là gần 4500 lần nhanh hơn. Tất nhiên, nó phụ thuộc rất nhiều vào những gì bạn sẽ làm với tập tin. Thay đổi byte đầu tiên hầu như không đại diện. Nhưng bằng cách sử dụng phương pháp này, bạn có một khởi đầu trên hai khác, và vì hầu hết các hệ điều hành có đệm tốt của đĩa, tốc độ có thể rất tốt quá.
(Nếu bạn không được phép chỉnh sửa tệp và vì vậy muốn tránh chi phí tạo bản sao làm việc, có một vài cách để tăng tốc độ. Nếu bạn có thể chọn hệ thống tệp, Btrfs có copy-on-write hoạt động sao chép tệp - thực hiện hành động lấy bản sao của tệp hầu như tức thì. Có thể đạt được hiệu ứng tương tự bằng ảnh chụp LVM của bất kỳ hệ thống tệp nào.)
Bạn sẽ làm gì với 'luồng'? Đọc nó?? –
Bạn đang sử dụng Python 2.x hoặc 3.x? –
@JohnMachin: Tôi cũng muốn đọc và sửa đổi nó. Câu hỏi này nói chung về Python, nếu có sự khác biệt giữa 2.x và 3.x, hãy nói – zaharpopov