2011-11-23 41 views
5

Tôi đang cố gắng xử lý nội dung của một con tarfile bằng cách sử dụng multiprocessing.Pool. Tôi có thể sử dụng thành công việc thực hiện ThreadPool trong mô-đun đa xử lý, nhưng muốn có thể sử dụng các tiến trình thay vì các luồng vì nó có thể nhanh hơn và loại bỏ một số thay đổi được thực hiện cho Matplotlib để xử lý môi trường đa luồng. Tôi nhận được một lỗi mà tôi nghi ngờ có liên quan đến quá trình không chia sẻ không gian địa chỉ, nhưng tôi không chắc chắn làm thế nào để sửa chữa nó:Làm thế nào tôi có thể xử lý một tarfile với một hồ bơi đa xử lý Python?

Traceback (most recent call last): 
    File "test_tarfile.py", line 32, in <module> 
    test_multiproc() 
    File "test_tarfile.py", line 24, in test_multiproc 
    pool.map(read_file, files) 
    File "/ldata/whitcomb/epd-7.1-2-rh5-x86_64/lib/python2.7/multiprocessing/pool.py", line 225, in map 
    return self.map_async(func, iterable, chunksize).get() 
    File "/ldata/whitcomb/epd-7.1-2-rh5-x86_64/lib/python2.7/multiprocessing/pool.py", line 522, in get 
    raise self._value 
ValueError: I/O operation on closed file 

Chương trình thực tế phức tạp hơn, nhưng đây là một ví dụ về những gì tôi đang làm điều đó tái tạo các lỗi:

from multiprocessing.pool import ThreadPool, Pool 
import StringIO 
import tarfile 

def write_tar(): 
    tar = tarfile.open('test.tar', 'w') 
    contents = 'line1' 
    info = tarfile.TarInfo('file1.txt') 
    info.size = len(contents) 
    tar.addfile(info, StringIO.StringIO(contents)) 
    tar.close() 

def test_multithread(): 
    tar = tarfile.open('test.tar') 
    files = [tar.extractfile(member) for member in tar.getmembers()] 
    pool = ThreadPool(processes=1) 
    pool.map(read_file, files) 
    tar.close() 

def test_multiproc(): 
    tar = tarfile.open('test.tar') 
    files = [tar.extractfile(member) for member in tar.getmembers()] 
    pool = Pool(processes=1) 
    pool.map(read_file, files) 
    tar.close() 

def read_file(f): 
    print f.read() 

write_tar() 
test_multithread() 
test_multiproc() 

tôi nghi ngờ rằng một cái gì đó không ổn khi đối tượng TarInfo được truyền vào quá trình khác, nhưng phụ huynh TarFile không, nhưng tôi không chắc chắn làm thế nào để sửa chữa nó trong trường hợp đa xử lý. Tôi có thể làm điều này mà không cần phải trích xuất các tập tin từ tarball và ghi chúng vào đĩa?

Trả lời

5

Bạn không chuyển đối tượng TarInfo vào quy trình khác, bạn đang chuyển kết quả của tar.extractfile(member) vào quá trình khác, nơi member là đối tượng TarInfo. Phương thức extractfile(...) trả về một đối tượng giống như tệp, trong số những thứ khác, phương thức read() hoạt động dựa trên tệp tar gốc bạn đã mở với tar = tarfile.open('test.tar').

Tuy nhiên, bạn không thể sử dụng tệp mở từ một quy trình trong quy trình khác, bạn phải mở lại tệp. Tôi thay thế test_multiproc() của bạn với điều này:

def test_multiproc(): 
    tar = tarfile.open('test.tar') 
    files = [name for name in tar.getnames()] 
    pool = Pool(processes=1) 
    result = pool.map(read_file2, files) 
    tar.close() 

Và thêm này:

def read_file2(name): 
    t2 = tarfile.open('test.tar') 
    print t2.extractfile(name).read() 
    t2.close() 

và đã có thể để có được mã của bạn làm việc.

+0

Hỗ trợ của Windows: 'if name == '__main__': test_multiproc()'. Không có ngã ba trong Windows, do đó, mô-đun được nhập khẩu trong quá trình mới ban đầu dưới tên ''__parents_main __'', và sau đó tên được thay đổi trở lại ''__main __''. Vì vậy, bạn có thể bảo vệ các câu lệnh mà bạn không muốn chạy trong các tiến trình con bằng cách sử dụng khối 'if'. – eryksun

+0

Tác phẩm này, nhưng yêu cầu tôi phải mở lại tarfile trong mọi quy trình. Có cách giải quyết nào khác cho phép truy cập chỉ đọc vào một bộ mô tả tệp giữa các tiến trình không? –

+0

Tôi đã kết thúc thiết lập cờ để đọc trước dữ liệu trước khi tắt nhiều quá trình. Cảm ơn bạn! –

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