2010-01-30 29 views
8

Để tránh liên tục truy cập vào máy chủ SOAP trong quá trình phát triển, tôi đang cố lưu vào bộ nhớ cache kết quả để tôi có thể chạy phần còn lại của mã mà không phải truy vấn máy chủ mỗi lần.Làm cách nào để tôi có thể lấy kết quả?

Với mã bên dưới, tôi nhận được PicklingError: Can't pickle <class suds.sudsobject.AdvertiserSearchResponse at 0x03424060>: it's not found as suds.sudsobject.AdvertiserSearchResponse khi tôi cố gắng chọn một kết quả phù hợp. Tôi đoán điều này là do các lớp được tạo động.

import pickle 
from suds.client import Client 

client = Client(...) 
result = client.service.search(...) 

file = open('test_pickle.dat', 'wb') 
pickle.dump(result, file, -1) 
file.close() 

Nếu tôi thả các phiên bản -1 giao thức từ pickle.dump(result, file, -1), tôi nhận được một lỗi khác nhau:

TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled 

là tẩy những điều đúng đắn nên làm gì? Tôi có thể làm cho nó hoạt động được không? Có cách nào tốt hơn?

Trả lời

8

Vì thông báo lỗi bạn hiện đang cố gắng cho bạn biết, bạn đang cố gắng chọn các trường hợp là không phải có thể chọn (trong giao thức chọn cũ kế thừa bạn đang sử dụng) vì lớp của chúng xác định __slots__ nhưng không phải là phương pháp __getstate__.

Tuy nhiên, ngay cả việc thay đổi lớp học cũng không giúp được vì sau đó bạn sẽ gặp phải sự cố khác - sự cố bạn đã xác định là có khả năng do các lớp được tạo động. Tất cả các giao thức pickle tuần tự hóa các lớp (và chức năng) "theo tên", về cơ bản hạn chế chúng ở các tên cấp cao nhất trong các mô-đun của chúng. Và, tuần tự hóa một cá thể hoàn toàn không yêu cầu tuần tự hóa lớp (làm cách nào khác bạn có thể tái tạo lại cá thể sau này nếu lớp đó không nằm xung quanh ?!). Vì vậy, bạn sẽ cần phải lưu và tải lại dữ liệu của bạn theo cách khác, phá vỡ sự phụ thuộc trực tiếp hiện tại của bạn vào các lớp cụ thể trong suds.sudsobject có lợi tùy thuộc vào giao diện (được chính thức hóa hoặc chỉ được xác định bằng cách gõ vịt) có thể thực hiện cả hai bởi các lớp cụ thể như vậy khi bạn đang thực sự truy cập vào máy chủ SOAP, hoặc đơn giản hơn "tự chế" khi bạn đang tải dữ liệu từ một tệp. (Dữ liệu đại diện cho trạng thái ví dụ không thể nghi ngờ là dict, vì vậy bạn có thể ép nó qua pickle nếu bạn thực sự muốn, ví dụ như thông qua mô-đun copy_reg cho phép bạn tùy chỉnh các giao thức serialize/deserialize cho các đối tượng mà bạn buộc phải xử lý không xâm lấn [[vì vậy bạn không thể đi xung quanh thêm __getstate__ hoặc tương tự cho lớp học của họ]] - vấn đề sẽ chỉ đến nếu có một lưới giàu tham chiếu lẫn nhau giữa các đối tượng đó).

+1

Có cách nào để có được định nghĩa của một lớp được tạo động để nó có thể được lưu vào một tập tin và sau đó được sử dụng như một lớp bình thường? – tponthieux

2

Bạn đang tự chọn đối tượng lớp và không phải là đối tượng của lớp. Điều này sẽ không hoạt động nếu đối tượng lớp được tạo lại. Tuy nhiên, các trường hợp pickling của lớp sẽ làm việc miễn là đối tượng lớp tồn tại.

+0

Tôi nghĩ rằng tôi làm theo những gì bạn đang nói, nhưng khi đã chọn, nhập (kết quả) là và kết quả .__ class__ là vì vậy tôi không cố gắng để chọn ví dụ? – Mat

+0

Từ mã được dán, có vẻ như bạn đang tẩy một thể hiện, nhưng lỗi bạn đang đề cập đến cho thấy bạn đang chọn một lớp. –

+0

Được rồi, tôi sẽ không hoàn toàn hạt sau đó :) Tôi nhận được một lỗi khác nhau nếu tôi thả -1 cho giao thức mới nhất mà tôi sẽ sửa đổi các câu hỏi để bao gồm xem nếu nó giảm bất kỳ ánh sáng. – Mat

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