2014-07-11 4 views
1

내 응용 프로그램은 사용자로부터 하나 이상의 URL (일반적으로 3-4 개의 URL)을 수신하고 해당 URL에서 특정 데이터를 긁어내어 해당 데이터를 데이터베이스에 씁니다. 그러나, 그 데이터를 근근이 살아가는 데는 조금 시간이 걸리기 때문에, 각 스크래핑을 별도의 스레드에서 실행하여 데이터베이스에 대한 스크래핑 + 쓰기가 백그라운드에서 계속 진행될 수 있도록하여 사용자가 계속 사용할 필요가 없도록했습니다. 기다리는. 라인 new_movie 인쇄 올바른 폐기 데이터를 수행하는 동안 피라미드 : 다중 스레드 데이터베이스 작업

@view_config(route_name="add_movie", renderer="templates/add_movie.jinja2") 
def add_movie(request): 
    post_data = request.POST 

    if "movies" in post_data: 
     movies = post_data["movies"].split(os.linesep) 

     for movie_id in movies:   
      movie_thread = Thread(target=store_movie_details, args=(movie_id,)) 
      movie_thread.start() 

    return {} 

def store_movie_details(movie_id): 

    movie_details = scrape_data(movie_id) 
    new_movie = Movie(**movie_details) # Movie is my model. 

    print new_movie # Works fine. 

    print DBSession.add(movies(**movie_details)) # Returns None. 

DBSession.add()이 작동하지 않습니다

가를 구현하기 위해, 나는 (관련 부분 만)이있다. 사실만 반환합니다.

스레드를 제거하고 store_movie_details() 메서드를 호출하면 올바르게 작동합니다.

무슨 일 이니?

답변

2

첫째, Session.add()의 SA 문서에는 메서드의 반환 값에 대한 언급이 없으므로 None을 반환 할 것으로 예상됩니다.

둘째, 나는 당신이 그 : 피라미드의 요청 - 응답주기에 묶여 셋째

, 표준 피라미드 세션 (ZopeTransactionExtension로 구성된 하나) 무엇이든 세션하지 movies(**movie_details)new_movie를 추가하는 의미 생각 상황에 예기치 않은 동작이 발생할 수 있습니다. store_movie_details에서 수동으로 커밋해야하는 별도의 세션을 구성해야합니다. 이 세션은 scoped_session을 사용해야하므로 세션 개체는 스레드 로컬이며 스레드간에 공유되지 않습니다.

from sqlalchemy.orm import scoped_session 
from sqlalchemy.orm import sessionmaker 

session_factory = sessionmaker(bind=some_engine) 
AsyncSession = scoped_session(session_factory) 

def store_movie_details(movie_id): 

    session = AsyncSession() 
    movie_details = scrape_data(movie_id) 
    new_movie = Movie(**movie_details) # Movie is my model. 

    session.add(new_movie) 
    session.commit() 

는 그리고 물론,이 방법은 매우 가벼운 작업에만 적합합니다, 당신은 때때로 작업을 잃는 괜찮다면 (할 때 예를 들어, 웹 서버 다시 시작). Antoine Leclair의 제안처럼 셀라 리 등을 좀 더 진지하게 살펴보십시오.

+0

완벽하게 작동했습니다. 고마워요! – tripatheea

0

응답이 리턴되면 트랜잭션 관리자가 트랜잭션을 닫습니다. DBSession은 응답이 리턴 될 때 다른 스레드에서 트랜잭션을 갖지 않습니다. 또한 스레드간에 트랜잭션을 공유하는 것은 좋지 않습니다.

이것은 작업자를위한 일반적인 사용 사례입니다. Celery 또는 RQ을 확인하십시오.