2010-06-06 41 views
5

Tôi đang phát triển một ứng dụng trong Google App Engine. Một trong những phương pháp của tôi là không bao giờ hoàn thành, mà làm cho tôi nghĩ rằng nó bị bắt trong một vòng lặp vô hạn. Tôi đã nhìn chằm chằm vào nó, nhưng không thể hiểu được.Python: tại sao mã này mất mãi mãi (vòng lặp vô hạn?)

Tuyên bố từ chối trách nhiệm: Tôi đang sử dụng http://code.google.com/p/gaeunitlink text để chạy thử nghiệm của mình. Có lẽ nó hành động kỳ quặc?

Đây là chức năng có vấn đề:

def _traverseForwards(course, c_levels): 
    ''' Looks forwards in the dependency graph ''' 
    result = {'nodes': [], 'arcs': []} 

    if c_levels == 0: 
     return result 

    model_arc_tails_with_course = set(_getListArcTailsWithCourse(course)) 
    q_arc_heads = DependencyArcHead.all() 

    for model_arc_head in q_arc_heads: 
     for model_arc_tail in model_arc_tails_with_course: 
      if model_arc_tail.key() in model_arc_head.tails: 
       result['nodes'].append(model_arc_head.sink) 
       result['arcs'].append(_makeArc(course, model_arc_head.sink)) 

       # rec_result = _traverseForwards(model_arc_head.sink, c_levels - 1) 

       # _extendResult(result, rec_result) 

    return result 

Ban đầu, tôi nghĩ rằng nó có thể là một lỗi đệ quy, nhưng tôi nhận xét ra các đệ quy và vấn đề vẫn còn. Nếu chức năng này được gọi với c_levels = 0, nó sẽ hoạt động tốt.

Các mô hình nó tham chiếu: chức năng

class Course(db.Model): 
    dept_code = db.StringProperty() 
    number = db.IntegerProperty() 
    title = db.StringProperty() 
    raw_pre_reqs = db.StringProperty(multiline=True) 
    original_description = db.StringProperty() 

    def getPreReqs(self): 
     return pickle.loads(str(self.raw_pre_reqs)) 

    def __repr__(self): 
     return "%s %s: %s" % (self.dept_code, self.number, self.title) 

class DependencyArcTail(db.Model): 
    ''' A list of courses that is a pre-req for something else ''' 
    courses = db.ListProperty(db.Key) 

    def equals(self, arcTail): 
     for this_course in self.courses: 
      if not (this_course in arcTail.courses): 
       return False 

     for other_course in arcTail.courses: 
      if not (other_course in self.courses): 
       return False 

     return True 

class DependencyArcHead(db.Model): 
    ''' Maintains a course, and a list of tails with that course as their sink ''' 
    sink = db.ReferenceProperty() 
    tails = db.ListProperty(db.Key) 

Utility nó tham chiếu:

def _makeArc(source, sink): 
    return {'source': source, 'sink': sink} 

def _getListArcTailsWithCourse(course): 
    ''' returns a LIST, not SET 
     there may be duplicate entries 
    ''' 
    q_arc_heads = DependencyArcHead.all() 
    result = [] 
    for arc_head in q_arc_heads: 
     for key_arc_tail in arc_head.tails: 
      model_arc_tail = db.get(key_arc_tail) 
      if course.key() in model_arc_tail.courses: 
       result.append(model_arc_tail) 

    return result 

Tôi có thiếu một cái gì đó khá rõ ràng ở đây, hoặc là GAEUnit hành động lên?

Ngoài ra - thử nghiệm chạy chậm này không có nhiều hơn 5 kiểu bất kỳ trong kho dữ liệu. Tôi biết điều này có khả năng chậm, nhưng ứng dụng của tôi chỉ thực hiện điều này một lần rồi sau đó lưu trữ nó.

Trả lời

3

Bỏ qua nhận xét đã được nhận xét, tôi không nghĩ đây là vòng lặp vô hạn - bạn chỉ đang thực hiện một số vòng lặp cho các tập hợp kết quả hữu hạn.

Tuy nhiên, có vẻ như điều này sẽ là thực sự là chậm. Bạn đang lặp qua toàn bộ các bảng và sau đó thực hiện nhiều truy vấn kho dữ liệu hơn trong mỗi vòng lặp lồng nhau. Có vẻ như không chắc rằng loại yêu cầu này sẽ hoàn thành một cách kịp thời trên GAE trừ khi các bảng của bạn thực sự rất nhỏ.


Một số thô số:

Nếu H = # của các thực thể trong DepedencyArcHeadT = trung bình # đuôi trong mỗi DependencyArcHead thì:

  • _getListArcTailsWithCourse đang làm khoảng H*T truy vấn (understimate). Trong trường hợp "tệ nhất", result được trả về từ chức năng này sẽ có các phần tử H*T.
  • _traverseForwards vòng lặp trên tất cả các kết quả này H lần và do đó thực hiện một truy vấn H * (H * T) khác.
  • Ngay cả khi HT chỉ ở thứ tự 10 giây, bạn có thể đang thực hiện hàng nghìn truy vấn. Nếu chúng lớn hơn, thì ... (và điều này bỏ qua bất kỳ truy vấn bổ sung nào bạn sẽ làm nếu bạn bỏ ghi chú cuộc gọi đệ quy).

Tóm lại, tôi nghĩ bạn có thể muốn tổ chức dữ liệu của mình hơi khác một chút nếu có thể. Tôi muốn đưa ra một gợi ý cụ thể, nhưng chính xác những gì bạn đang cố gắng làm không rõ ràng với tôi.

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