2011-03-31 1 views
3

RSS 피드의 항목을 읽고 JSON 형식의 개별 항목을 CouchDB 데이터베이스에 저장하는 스크립트가 있습니다.Python CouchDB는 피드 파서 항목에서 생성 된 dict를 저장할 수 없습니까? ('no'속성)

내 코드의 흥미로운 부분은 다음과 같은 :

Feed = namedtuple('Feed', ['name', 'url']) 

couch = couchdb.Server(COUCH_HOST) 
couch.resource.credentials = (COUCH_USER, COUCH_PASS) 

db = couch['raw_entries'] 

for feed in map(Feed._make, csv.reader(open("feeds.csv", "rb"))): 
    d = feedparser.parse(feed.url) 
    for item in d.entries: 
     db.save(item) 

내가 그 코드를 실행하려고 할 때, 나는 db.save(item)에서 다음과 같은 오류 얻을 :

AttributeError: object has no attribute 'read' 

확인을, 그래서 그런 다음 약간의 디버깅을했습니다 ...

for feed in map(Feed._make, csv.reader(open("feeds.csv", "rb"))): 
    d = feedparser.parse(feed.url) 
    for item in d.entries: 
     print(type(item)) 

결과는 <class 'feedparser.FeedParserDict'>입니다. - 아아, feedparser가 자체 dict 유형을 사용하고 있습니다 ... 음, 명시 적으로 캐스팅하려고하면 dict?

for feed in map(Feed._make, csv.reader(open("feeds.csv", "rb"))): 
    d = feedparser.parse(feed.url) 
    for item in d.entries: 
     db.save(dict(item)) 

Traceback (most recent call last): 
    File "./feedchomper.py", line 32, in <module> 
    db.save(dict(item)) 
    File "/home/dealpref/lib/python2.7/couchdb/client.py", line 407, in save 
_, _, data = func(body=doc, **options) 
    File "/home/dealpref/lib/python2.7/couchdb/http.py", line 399, in post_json 
status, headers, data = self.post(*a, **k) 
    File "/home/dealpref/lib/python2.7/couchdb/http.py", line 381, in post 
**params) 
    File "/home/dealpref/lib/python2.7/couchdb/http.py", line 419, in _request 
credentials=self.credentials) 
    File "/home/dealpref/lib/python2.7/couchdb/http.py", line 239, in request 
    resp = _try_request_with_retries(iter(self.retry_delays)) 
    File "/home/dealpref/lib/python2.7/couchdb/http.py", line 196, in _try_request_with_retries 
    return _try_request() 
    File "/home/dealpref/lib/python2.7/couchdb/http.py", line 222, in _try_request 
    chunk = body.read(CHUNK_SIZE) 
AttributeError: 'dict' object has no attribute 'read' 

w-what? 내가 여기서 무엇을 놓치고

some_dict = dict({'foo': 'bar'}) 
print(type(some_dict)) 
db.save(some_dict) 

다음 작품 잘와 유형이 여전히 dict 때문에 즉, 이해가되지 않습니다?

+1

이러한 오류에 대한 스택 추적을 게시 할 수 있습니까? 오류가 CouchDB 모듈에서 어딘가에있을 가능성이 있습니다. 'dict' 객체는'read()'메소드를 가지고 있지 않지만, 빨간 청어가 될 수 있습니다. – kindall

+0

@kindall - stacktrace 전체를 게시했습니다 ... CouchDB가 어떤 이유로 든 청크 업로드를하려고하는 것 같습니다 (아마도 dict가 크기 때문에)? 그러나, 손에서 dict을 구성하여 동작을 복제 할 수 없습니다 (즉, 손으로 직접 작성하면 절약 할 수 있습니다 ...). – ashgromnies

+1

네, 당신의 딕트가 어떤 이유로 든 파일이라고 생각하는 것 같습니다. 매우 이상합니다. – kindall

답변

4

구조를 JSON으로 serialize 한 다음 다시 CouchDB에 전달하는 Python dict에 대한 방법을 찾았습니다. 그런 다음 JSON으로 다시 reserialize하여 저장합니다 (예, 이상하지만 좋지는 않지만 작동합니까?)

time_structrepreval '일 수 없으므로 덤프 용 사용자 지정 직렬 변환기 방법을 사용해야했습니다.

출처 : http://diveintopython3.org/serializing.html

코드 :

#!/usr/bin/env python2.7 

from collections import namedtuple 
import csv 
import json 
import time 

import feedparser 
import couchdb 

def to_json(python_object): 
    if isinstance(python_object, time.struct_time): 
     return {'__class__': 'time.asctime', 
       '__value__': time.asctime(python_object)} 

    raise TypeError(repr(python_object) + ' is not JSON serializable') 

Feed = namedtuple('Feed', ['name', 'url']) 

COUCH_HOST = 'http://mycouch.com' 
COUCH_USER = 'user' 
COUCH_PASS = 'pass' 

couch = couchdb.Server(COUCH_HOST) 
couch.resource.credentials = (COUCH_USER, COUCH_PASS) 

db = couch['raw_entries'] 

for feed in map(Feed._make, csv.reader(open("feeds.csv", "rb"))): 
    d = feedparser.parse(feed.url) 
    for item in d.entries: 
     j = json.dumps(item, default=to_json) 
     db.save(json.loads(j)) 
1

어쩌면 파이썬 CouchDB를 버그가 있습니다. 당신은 받아들이는 것에 대해 충분히 진보적이지 않다고 말할 수 있습니다.

하지만 기본적으로 CouchDB는 JSON을 저장합니다. 당신은 당신의 언어로 "JSON"이 무엇이든간에 작업해야합니다. 분명히 파이썬은 dict이라는 것을 의미합니다.

CouchDB를 호출하기 전에 모든 유형을 일반 Python dict로 변환하는 방법을 알아내는 것이 가장 좋은 방법 일 것입니다. 어쩌면 이것이 가장 "올바른"해결책이 아니 겠지만, 그것이 가장 빠를 것이라고 생각됩니다.

파이썬이 녹슬 었습니다. dict(foo)이 아닌 사치품을 반환 할 수 있습니까? 어쩌면 FeedParserDict 서브 클래스 dict을 호출 한 다음 dict()을 호출하면 메타 프로그래밍을 사용하여 자체를 반환합니까? type(dict(item))이 명백히 평범한 파이썬 딕트인지 확인할 수 있습니까?

Javascript에서 자주 사용되는 트릭은 JSON과 같은 시리얼 라이저를 왕복하는 것입니다. pickle.loads(pickle.dumps(item))과 같은 것입니다. 이는 핵심 데이터의 평범한 복사본을 보장합니다.

+0

을 수행한다. 'type (dict (item)) '결과에 대해 알려주십시오. 나의 가설이 틀렸다면, 아마도 다른 것이 울릴 것입니다. 그런데 훌륭한 질문입니다! – JasonSmith

+0

'type (dict (item))'은'dict'을 반환합니다 :) – ashgromnies

4

메일 링리스트에 답변되었지만 기본적으로 피드 배너 항목에 무손실하게 JSON에 직렬화 할 수없는 데이터가 포함되어 있기 때문에 이런 일이 발생합니다. time.struct_time 인스턴스.불행히도 couchdb-python은 실제 오류를 가리면서 파일이라고 가정합니다.