2012-09-07 35 views
6

Tôi phải thực hiện một số công việc dài trong ứng dụng Flask của mình. Và tôi muốn làm điều đó không đồng bộ. Chỉ cần bắt đầu làm việc, và sau đó kiểm tra trạng thái từ javascript.Quy trình bình thường dài

Tôi đang cố gắng để làm một cái gì đó như:

@app.route('/sync') 
def sync(): 
    p = Process(target=routine, args=('abc',)) 
    p.start() 

    return "Working..." 

Nhưng điều này tạo ra công nhân gunicorn không còn tồn tại.

Làm cách nào để giải quyết? Tôi có nên dùng thứ gì đó như Celery không?

Trả lời

11

Có nhiều tùy chọn. Bạn có thể phát triển giải pháp của riêng bạn, sử dụng Celery hoặc Twisted (Tôi chắc chắn có nhiều tùy chọn đã được tạo sẵn ở đó nhưng đó là những tùy chọn phổ biến nhất).

Phát triển giải pháp nội bộ của bạn không khó. Bạn có thể sử dụng mô-đun multiprocessing của thư viện chuẩn Python:

  • Khi tác vụ đến, bạn chèn hàng vào cơ sở dữ liệu của bạn với id công việc và trạng thái.
  • Sau đó, khởi chạy quy trình để thực hiện công việc cập nhật trạng thái hàng khi kết thúc.
  • Bạn có thể có một chế độ xem để kiểm tra xem tác vụ đã hoàn tất chưa, điều đó thực sự chỉ kiểm tra trạng thái trong tương ứng.

Tất nhiên bạn phải nghĩ nơi bạn muốn lưu trữ kết quả tính toán và điều xảy ra với lỗi.

Đi với cần tây cũng dễ dàng. Nó sẽ giống như sau. Để xác định một chức năng được thực hiện không đồng bộ:

@celery.task 
def mytask(data): 

    ... do a lot of work ... 

Sau đó, thay vì gọi nhiệm vụ trực tiếp, giống như mytask(data), trong đó sẽ thực hiện nó ngay lập tức, sử dụng delay phương pháp:

result = mytask.delay(mydata) 

Cuối cùng, bạn có thể kiểm tra xem kết quả có sẵn hay không với ready:

result.ready() 

Tuy nhiên, hãy nhớ lại R để sử dụng Celery bạn phải chạy một quy trình công nhân bên ngoài.

Tôi chưa từng nhìn vào Twisted vì vậy tôi không thể nói cho bạn biết nó có phức tạp hơn hay không (nhưng bạn cũng nên làm những gì bạn muốn làm).

Trong mọi trường hợp, bất kỳ giải pháp nào cũng hoạt động tốt với Flask. Để kiểm tra kết quả, không quan trọng ở tất cả nếu bạn sử dụng Javascript. Chỉ cần thực hiện chế độ xem để kiểm tra trạng thái trả về JSON (bạn có thể sử dụng Flask's jsonify).

+0

Vâng, tôi thực sự có mọi thứ mà bạn đã nói về lưu trữ kết quả trong DB. Vấn đề chính với việc thực hiện giải pháp của riêng tôi là khi tôi đang sử dụng 'multiprocessing', nó làm cho nhân viên gunicorn không còn tồn tại. – sashab

+0

Rất tiếc, tôi xin lỗi vì tôi đã hiểu sai câu hỏi của bạn. Có vẻ như vấn đề của bạn là quá trình cha mẹ của bạn đang kết thúc sau câu lệnh trả về, điều này sẽ giết chết quá trình con bạn đã tạo ra một cách hiệu quả. Để tránh điều đó, bạn chỉ cần daemonize con trước khi cha mẹ thoát (tức là tách nó) [python-daemon] (http://pypi.python.org/pypi/python-daemon/) – pacha

+0

Tôi nhận được 'ValueError: I/O hoạt động trên tập tin đóng' khi sử dụng nó với đa xử lý. Có vẻ như tôi cần sử dụng Popen. Thiết lập 'Process(). Daemon = True' cũng không giúp ích gì. – sashab

2

Tôi sẽ sử dụng một nhà môi giới thư như rabbitmq hoặc activemq. Quy trình bình sẽ thêm công việc vào hàng đợi tin nhắn và một quy trình công nhân chạy dài (hoặc các quy trình của hồ bơi hoặc công nhân) sẽ lấy việc làm ra khỏi hàng đợi để hoàn thành chúng. Quy trình công nhân có thể cập nhật cơ sở dữ liệu để cho phép máy chủ bình để biết trạng thái hiện tại của công việc và chuyển thông tin này cho khách hàng.

Sử dụng cần tây có vẻ là một cách hay để thực hiện việc này.

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