2011-11-17 19 views
10

này được nên bị hỏng, tôi hy vọng bạn thương xót với tôi:Làm thế nào để kết hợp callLater và addCallback?

reactor.callLater(0, myFunction, parameter1).addCallback(reactor.stop) 
reactor.run() 

myFunction trả về một chậm.

Tôi hy vọng nó là rõ ràng những gì tôi muốn làm:

  • ngay sau khi lò phản ứng đang chạy, tôi muốn gọi myFunction. Đó là lý do tại sao tôi đang sử dụng 0 làm tham số trễ. Không có cách nào khác ngoại trừ callLater? Có vẻ buồn cười khi vượt qua sự chậm trễ là 0.
  • Tôi muốn dừng lò phản ứng ngay sau khi myFunction hoàn thành nhiệm vụ.

Những vấn đề mà tôi có cho đến nay:

  • AttributeError: DelayedCall instance has no attribute 'addCallback'. Đủ công bằng! Làm thế nào để đặt một cuộc gọi lại trong chuỗi gọi lại bắt đầu bằng myFunction sau đó?
  • exceptions.TypeError: stop() takes exactly 1 argument (2 given).

Để giải quyết vấn đề thứ hai tôi đã phải xác định một chức năng đặc biệt:

def stopReactor(result): 
    gd.log.info('Result: %s' % result) 
    gd.log.info('Stopping reactor immediatelly') 
    reactor.stop() 

Và thay đổi mã để:

reactor.callLater(0, myFunction, parameter1).addCallback(stopReactor) 
reactor.run() 

(vẫn không làm việc vì vấn đề callLater, nhưng stopReactor sẽ hoạt động ngay bây giờ)

Có thực sự không có cách nào khác để gọi reactor.stop ngoại trừ bằng de fining một chức năng phụ?

Trả lời

19

IReactorTime.callLaterDeferred được trộn với nhau bằng twisted.internet.task.deferLater.

from twisted.internet import reactor, task 

d = task.deferLater(reactor, 0, myFunction, parameter1) 
d.addCallback(lambda _: reactor.stop()) 
reactor.run() 
+0

Tôi thấy tùy chọn này rất dễ đọc. Các bit 'lambda bỏ qua 'trông kỳ diệu với tôi: bạn có thể làm rõ những gì nó chính xác không? – dangonfast

+4

Các cuộc gọi lại trên hoãn lại được gọi với một đối số. 'reactor.stop' không có bất kỳ đối số nào. 'lambda bị bỏ qua: reactor.stop()' chấp nhận và đối số, bỏ qua nó và gọi 'reactor.stop' mà không có đối số. –

+3

Nó sẽ là một chút thông thường hơn để viết: 'lambda _: reactor.stop' – DonGar

1

Tôi muốn dừng lò phản ứng ngay khi myFunction đã hoàn thành tác vụ.

Vì vậy, tạo trình bao bọc có hoạt động của myFunction và sau đó dừng lò phản ứng?

def wrapper(reactor, *args): 
    myFunction(*args) 
    reactor.stop() 

reactor.callLater(0, wrapper, reactor, ...) 
0

Bạn cần phải đính kèm cuộc gọi lại vào trả chậm mà hàm myFunction trả về, vì callLater không trả về hàm. Một cái gì đó như thế này có thể hoạt động:

reactor.callLater(0, lambda: myFunction(parameter1).addCallback(lambda _: reactor.stop()) 

Nhưng điều này không được kiểm tra.

Bạn cần phải viết một hàm mới (ở đây lambda _: reactor.stop()) bởi vì các cuộc gọi lại đến trì hoãn luôn mang kết quả đến lúc đó.Nếu bạn thấy mình muốn sử dụng callbacks cho tác dụng phụ của họ và bạn không quan tâm đến việc tuyên truyền các giá trị thường xuyên, bạn có thể định nghĩa một hàm helper nhỏ:

def ignoringarg(f): 
    return lambda _: f() 

Và sau đó làm:

reactor.callLater(0, lambda: myFunction(paramater1).addCallback(ignoringarg(reactor.stop))) 

(Điều sẽ thực sự gọn gàng là xác định __rshift__ (và tại chỗ tương tự) cho lớp Deferred để bạn có thể làm: myFunction(parameter1) >> reactor.stop, khi bạn muốn từ bỏ đối số hoặc myFunction(parameter1) >>= someotherfunc khi bạn muốn truyền đối số. Nếu bạn nghĩ rằng lạm dụng cú pháp haskellish là "gọn gàng", anyway.)

0

Nếu bạn cần kích hoạt gọi lại với một số hành động, chỉ cần thực hiện (có thể không cần phải trả lại hoãn lại hoặc smth). Chỉ cần làm rõ mọi thứ (sử dụng hoàn toàn trì hoãn):

from twisted.internet import reactor, defer 

# That will be our deferred to play with 
# it has callback and errback methods 
d = defer.Deferred() 

def my_function(x): 
    print 'function', x 
    # need to trigger deferred upon function run? 
    # Lets tell it to do so: 
    d.callback(x) 

# That's our callback to run after triggering `d`  
def d_callback(y): 
    print 'callback ', y 

# now let's bind that callback to be actually launched by `d` 
d.addCallback(d_callback) 

# now adding another callback just to stop reactor 
# note lambda simply helps to agree number of arguments 
d.addCallback(lambda data: reactor.stop()) 

# so we'll call `my_function` in 2 secs, then it runs 
# then it triggers `d` to fire its callbacks 
# then `d` actually detonates the whole chain of its added callbacks 

reactor.callLater(2, my_function, 'asdf') # 'asdf' is some stupid param 

# Here how it works 
print 'Lets start!' 
reactor.run() 
print 'Done!' 
Các vấn đề liên quan