2016-08-02 13 views
6

Tôi có hai chức năng trong python dịch vụ web Twisted Klein của tôi:Làm thế nào để thực thi mã không đồng bộ trong Twisted Klein?

@inlineCallbacks 
def logging(data): 
    ofile = open("file", "w") 
    ofile.write(data) 
    yield os.system("command to upload the written file") 

@APP.route('/dostuff') 
@inlineCallbacks 
def dostuff(): 
    yield logging(data) 
    print "check!" 
    returnValue("42") 

Khi os.system("command to upload the written file") chạy, nó sẽ hiển thị thông báo "bắt đầu tải lên" sau đó "upload hoàn thành". Tôi muốn làm cho hàm ghi nhật ký không đồng bộ để xử lý trong trình xử lý logging xảy ra sau khi dostuff xử lý in ra "kiểm tra!". (Tôi thực sự muốn xử lý xảy ra sau khi returnValue ("42"), nhưng cả hai đều đang làm cho chức năng ghi nhật ký như tôi nghĩ?)

Tôi nghĩ rằng tuyên bố lợi nhuận sẽ làm cho nó không chặn nhưng có vẻ như không phải là trường hợp , kiểm tra!" luôn được in sau khi "bắt đầu tải lên" và "tải lên hoàn tất". Tôi sẽ đánh giá cao nếu có ai có thể cho tôi một số phản hồi về nó vì tôi mới sử dụng mã hóa async và bị chặn trong thời gian này ...

Trả lời

3

Để làm cho mã của bạn không đồng bộ, bạn cần sử dụng Twisted Deferreds làm described here. Hoãn cung cấp cho bạn một API để thực thi mã không đồng bộ, chúng cho phép bạn gắn các hàm gọi lại vào các hàm của bạn và chúng thực thi mã trong vòng lặp sự kiện xoắn được quản lý bởi đối tượng lò phản ứng.

Tôi thấy hai cách tiềm năng để sử dụng Trì hoãn trong trường hợp của bạn.

1) Thực hiện nhiệm vụ trong nền với reactor.callLater()

Đây là ok nếu dostuff xử lý không quan tâm đến kết quả. Bạn có thể sử dụng reactor.callLater(). Bằng cách này, hàm async của bạn sẽ thực thi sau khi bạn trả về giá trị từ doStuff.

Vì vậy, một cái gì đó như thế này:

from klein import run, route, Klein 
from twisted.internet import defer, task, reactor 
import os 

app = Klein() 


def logging(data): 
    ofile = open("file", "w") 
    ofile.write(data) 
    result = os.system("ls") 
    print(result) 


@route('/') 
def dostuff(request): 
    reactor.callLater(0, logging, "some data") 
    print("check!") 
    return b'Hello, world!' 

run("localhost", 8080) 

Trình tự các sự kiện với mã này đang theo, đầu tiên "kiểm tra" được in, sau đó "hello world" phản ứng được trả về và trong suceeds kết thúc cuộc gọi async và in kết quả chạy os.system().

2016-08-11 08:52:33+0200 [-] check! 
2016-08-11 08:52:33+0200 [-] "127.0.0.1" - - [11/Aug/2016:06:52:32 +0000] "GET/HTTP/1.1" 200 13 "-" "curl/7.35.0" 
a.py file 

2) Thực hiện nhiệm vụ ở chế độ nền và nhận được kết quả với task.deferLater()

Nếu bạn quan tâm đến kết quả của chức năng 'ghi' của bạn, bạn cũng có thể đính kèm callback để đối tượng này và sử dụng twisted.internet.task API. Nếu bạn muốn đi theo con đường này, bạn cần phải cấu trúc lại xử lý của bạn để làm việc như thế này

@route('/') 
def dostuff(request): 
    def the_end(result): 
     print("executed at the end with result: {}".format(result)) 
    dfd = task.deferLater(reactor, 0, logging, "some data") 
    dfd.addCallback(the_end) 
    print("check!") 
    return b'Hello, world!' 

này để cách các sự kiện sẽ tương tự như trên, nhưng the_end chức năng sẽ được thực hiện ở cuối sau khi chức năng logging của bạn kết thúc.

2016-08-11 08:59:24+0200 [-] check! 
2016-08-11 08:59:24+0200 [-] "127.0.0.1" - - [11/Aug/2016:06:59:23 +0000] "GET/HTTP/1.1" 200 13 "-" "curl/7.35.0" 
a.py file 
2016-08-11 08:59:24+0200 [-] executed at the end with result: some result 
+0

Vì kiến ​​thức của tôi đối với Klein bị xoắn chủ yếu đến từ http://tavendo.com/blog/post/going-asynchronous-from-flask-to-twisted-klein/ Phản hồi của bạn giúp tôi rất nhiều. Tôi đã không thử nó nhưng tôi sẽ giả định nó là chính xác. Cảm ơn nhiều. Thực sự đánh giá cao nó. – JLTChiu

+0

Khi cập nhật, mã hoạt động, nhưng pyCharm và pylint của tôi hiển thị lỗi trên 'E: 512, 4: Module' twisted.internet.reactor 'không có thành viên' callLater '(không có thành viên) 'nhưng vấn đề là mã này có vẻ hoàn toàn tốt (Nó hoạt động như dự định). Có cách nào để sửa lỗi này? – JLTChiu

+1

trông giống như một số lỗi trong kiểm tra mã pycharm, có thể là một nền tảng cụ thể? Bạn sẽ phải kiểm tra những gì pycharm tìm kiếm khi thực hiện kiểm tra như thế này và tại sao nó không thành công với đoạn mã cụ thể này. Tôi sử dụng pycharm bản thân mình và tôi không thực sự tin tưởng cảnh báo phong cách của nó, nhiều người trong số họ là báo động sai. flake8 là công cụ tốt hơn để kiểm tra kiểu mã python IMO –

1

Tuyên bố 'lợi nhuận' không làm cho mọi việc xảy ra không đồng bộ. Nó chỉ ngăn chặn việc thực thi hàm chứa nó và trả về một đối tượng máy phát điện mà sau này có thể được sử dụng để lặp lại một chuỗi.

Dostuff() sẽ trả về đối tượng trình tạo. Không có gì sẽ xảy ra cho đến khi đối tượng máy phát điện đó được lặp lại đôi khi sau đó. Nhưng không có gì trong mã của bạn để làm cho điều này xảy ra. Tôi hy vọng thói quen dostuff của bạn sẽ tạo ra một lỗi cú pháp bởi vì nó chứa cả lợi nhuận và trả về không trống. Các thói quen khai thác gỗ sẽ không làm bất cứ điều gì bởi vì nó có chứa một sản lượng và máy phát điện nó trả về là không bao giờ được sử dụng.

Cuối cùng, thường trình ghi nhật ký sẽ cắt bớt tệp đầu ra của nó mỗi khi nó được gọi vì nó mở tệp nhật ký với chế độ 'w' trên mọi lời gọi.

Để thực thi không đồng bộ, bạn cần một số hình thức xử lý đa. Nhưng tôi không nghĩ rằng đó là cần thiết trong bối cảnh này. Chức năng ghi nhật ký của bạn khá nhẹ và nên chạy nhanh và không ảnh hưởng đến công việc của dostuff.

tôi sẽ đề nghị cố gắng một cái gì đó như thế này:

@inlineCallbacks 
def logging(data): 
    try: 
     logging._ofile.write(data + '\n') 
    except AttributeError: 
     logging._ofile = open("file", 'w') 
     logging._ofile.write(data + '\n') 

@APP.route('/dostuff') 
@inlineCallbacks 
def dostuff(): 
    logging("before!") 
    os.system("command to upload the written file") 
    logging("after!") 
    return("42") 

Ở đây chúng ta mở file đăng nhập một lần duy nhất, thời gian khai thác gỗ đầu tiên được gọi khi _ofile không được định nghĩa là một thuộc tính của khai thác gỗ. Trong các cuộc gọi tiếp theo, logging._ofile sẽ được mở và lệnh write trong khối try sẽ thành công.

Làm việc thường xuyên() gọi ghi nhật ký để cho biết chúng tôi sắp thực hiện công việc, thực sự thực hiện công việc, sau đó gọi ghi nhật ký để cho biết công việc đã được thực hiện và cuối cùng trả về giá trị mong muốn.

+0

doStuff không async trong mẫu mã của bạn, nó sẽ chặn trên 'cuộc gọi os.system', vì vậy "bắt đầu tải lên" và 'tải lên hoàn tất' sẽ được in trước khi trở về từ doStuff –

+0

True. Cảm ơn bạn đã tham gia với kiến ​​thức Twisted của bạn. –

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