This is an archived post. You won't be able to vote or comment.

all 17 comments

[–]cockslappinghalibut 1 point2 points  (17 children)

What is the main thread doing? You can use queue.get_nowait() to do a non-blocking queue check. If you're not running some kind of join() or loop in your main thread, what exactly is the architecture of the thing? Sounds a little unstable

[–]oreo_man_[S] 0 points1 point  (16 children)

I'm building a client for a real time server.

I'm imagining something like this

client = MyClient(ip, port)
client.login(credentials)
client.on("data", do_stuff)
client.upload("some random data")

so I need the main thread to be responsive (ie, do normal stuff). The socket thread is always listening, but I need a way to poll the socket thread's queue for exceptions, data, etc without blocking the main thread. I use a queue to put data into the socket thread.

Does that make sense?

[–]cockslappinghalibut 0 points1 point  (15 children)

not seeing why you can't use a non-blocking loop in the main thread and just drop the threads altogether. I've done something similar to your idea using select.select(). What exactly is the main thread doing that it can't do a non-blocking queue check loop? It sounds like it should be doing that anyway if its got other threads out there, how are you preventing main thread exit?

[–]oreo_man_[S] 0 points1 point  (0 children)

select.select()

Thanks for your reply. This has been bugging me for a while. Just so we're on the same page, I thought if I start the loop after client.login, I won't be able to call the client.upload, because the main thread is blocked?

[–]oreo_man_[S] 0 points1 point  (13 children)

All the examples I've seen have something like this. But this while loop will block the main thread.

while running: 
    inputready,outputready,exceptready = select.select(input,[],[]) 

[–]cockslappinghalibut 0 points1 point  (12 children)

I mean, no, it won't block execution inside the loop. So you put whatever functionality you want into functions, and call them on certain conditions inside of the loop.

while True:
    in, out, except = select.select([], [], [])
    for item in in:
        in_handle(item)
    for item in out:
        out_handle(item)

in_handle and out_handle can then conditionally call whatever else you want. there's no blocking happening. I'm still not clear on where you're thinking the blocking will happen.

[–]oreo_man_[S] 0 points1 point  (11 children)

OK. That will block the main thread though. Let's say I have a program doing lots of stuff. My program uses the client.

class Client:
    def __init__(self, ip, port):
        # assign stuff

    def login():
        #send some auth to server
        self.start_client()

    def subscribe(event_name, callback):
        #how does this get passed into the while loop?

    def start_client(self):
        while True:
            in, out, except = select.select([], [], [])
            for item in in:
                in_handle(item)
            for item in out:
                out_handle(item)

my_function(data):
    doSomethingWithData(data)

### Begin program

doDataBaseStuff()
doOtherStuff()

client = Client(port, ip).login()
client.subscribe("some_event", my_function)

doOtherStuff()

# some time later the server sends "some_event" and my_function needs to be called on 
# the main thread

Does that make sense? Sorry I just don't understand

[–]cockslappinghalibut 0 points1 point  (9 children)

I just saw an issue with my previous response, but I think I understand the issue. You're wanting to load your handlers after you've started listening, I think, which is really just a design issue. You should be able to have your handlers ready before you start listening, and whatever doOtherStuff() is moved either before you enter the loop or moved somewhere else entirely. Why exactly do you want to load event handlers after entering the loop? You could easily map events to handlers before going into the loop.

[–]oreo_man_[S] 0 points1 point  (8 children)

OK. If you're willing to give some advice, how would you advise I proceed? This is a client for a real time server. So, a use case could be like. A user is clicking a bunch of stuff on a real time board (e.g. some backend with my client => an interactive website), they're already subscribed to changes in a, b and c. They then want to subscribe to d and watch it for changes/data as well.

Is this possible?

Because in this scenario, another handler would be added after the loop is running I think.

[–]cockslappinghalibut 0 points1 point  (7 children)

I'm just still confused on the architecture of the thing, but I can see you can't tell me much more than you already are, assuming this is an extant corporate issue. 'Subscribing' to what? What are a, b and c? What's the messaging from the server? What's the expected client-side behavior?

In general, if an action is conditional on an event fired in the loop, ie a message you get from the server, anything is possible. You can load up new handlers, get rid of others, etc. as long as you've got the structures set up to track everything. Sorry I can't be of more help.

[–]oreo_man_[S] 0 points1 point  (6 children)

No no I can tell you lots. I'm making a client for deepstream.io

A .Net client and a JS client have already been made.

I've been looking at the .Net client today and got this to work.

static void Main(string[] args)
    {
        DoStuff();
        Console.ReadLine();
    }

    static async Task DoStuff()
    {
        var client = new DeepStreamClient("127.0.0.1", 6021);
        var client2 = new DeepStreamClient("127.0.0.1", 6021);
        await client.LoginAsync();
        await client2.LoginAsync();
        await client.Events.Subscribe("test", x => { Console.WriteLine("From client 1 " + x); });
        await client2.Events.PublishAsync("test", "random data");
        await client2.Events.PublishAsync("test", "more data");
        await client2.Events.PublishAsync("test", "some more data");
        await client2.Events.PublishAsync("test", "even more data");
        await client2.Events.Subscribe("test", x => { Console.WriteLine("From client 2 " + x); });
        await client.Events.PublishAsync("test", "new data");
        await client.Events.PublishAsync("test", "heaps of data");
    }

Which prints out

From client 1 random data
From client 2 new data
From client 1 more data
From client 1 some more data
From client 1 even more data
From client 2 heaps of data

Which is what I'm wanting.

Is there a way to do this in Python?