labrad / pylabrad

python interface for labrad
51 stars 31 forks source link

Labrad Server method stops! #348

Closed Xie-Tian closed 7 years ago

Xie-Tian commented 7 years ago

Hi! I wrote a labrad server with the aid of wiki. It works. But I ran into a problem. First, it's my code:

from labrad.server import LabradServer, setting
import numpy as np

SERVERNAME = 'tian'

class Tian_Server(LabradServer):

    name = SERVERNAME

    def initServer(self):
        self.dac = self.client.servers['laserdac_server']

    def set_supervisor_current(self,first_current):
        self.dac.set_individual_analog_voltages([('05', first_current)])
        print 'supervisor is set to:',first_current

    # scan current
    @setting(1)
    def scan_supervisor_2Ddata(self,c):

       "some code"

        for v in scan1:
            self.dac.set_individual_analog_voltages([('05', v)])
            print "scan supervisor: ", v

        "some code"

if __name__ == "__main__":
    from labrad import util
    server = Tian_Server()
    util.runServer( server )

I use dac.set_individual_analog_voltages([('05', v)]) to change the current set by another server.

When I run the scan_supervisor_2Ddata(), I can see from another computer that my current doesn't change actually.

And, when the method finished, the current will changed abruptly.

I was thinking that is there a problem about deferring?But I didn't find a method to deal with it. Thanks a lot!

maffoo commented 7 years ago

The code in server settings uses twisted and runs asynchronously. This means your call to set_individual_analog_voltages returns a twisted Deferred object and does not actually wait for the request to set the voltage to be completed. If you want to wait for that request to complete before printing or running more code, you need to insert a yield statement:

for v in scan1:
    yield self.dac.set_individual_analog_voltages([('05', v)])
    print "scan supervisor:", v
Xie-Tian commented 7 years ago

Thanks! I could add yield. But then I could not return strings in that method, like:

    @setting(1)
    def scan_supervisor_2Ddata(self,c):

       "some code"

        for v in scan1:
            self.dac.set_individual_analog_voltages([('05', v)])
            print "scan supervisor: ", v

        "some code"
       return <string>

It says python version < 3.3 do not allow 'return' with argument inside generator. I use python 2.7 for some reasons.

maffoo commented 7 years ago

You need to use the returnValue function from twisted to return values from asynchronous functions in python 2.7. See test_server.py for some examples.

Xie-Tian commented 7 years ago

Thanks!!!!! I'll read it now!!!! Also, I find that I could write all things in one method, then there's no need to return things. But it just makes my code ugly...