Python Forum

Full Version: Threading or pycharm pydev problem
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello.

I have been coding a program to manage crypto orders on an exchange. I have had a absence from coding for nearly 10 years so I have been learning a lot from scratch again and catching up to before.

The main bulk of the code is finished, for what I mainly need it to do, but I'm having problems after adding a background thread that watches for disconnections of another web socket thread, and also watches the current price of an asset, compares to a dict of triggers and will run a function depending on what type of trigger it was. (the web socket thread is disconnecting without error on rare occasions and I think it's a server side issue I have no control over)

So here's the problem. I have been working in Pycharm but I am new to it. I'm not sure if I'm doing something wrong with threading or this is just something with PyDev console in Pycharm. When I run this code in Pycharm, if I type > the_watcher_flag = 1, this is a global variable and should trigger the below if statement and close the_watcher() by the return statement. But this does not happen. I added a print statement to see what was happening and it always prints 0 after I have changed the flag to 1.
If I run the full script from > python3 main.py > from a terminal in the folder location, I get a hang, and a keyboard interrupt says it was failing to acquire a lock()***edit***I don't now it was a silly problem and program works fine from terminal***
I have come across lock in threading but I'm still in the middle of fully learning it.
The thing is, if I run the same main.py in IDLE3, the entire thing works perfectly, no hanging and changing the flag to 1 exits the thread as I would expect it to.
I'm just scratching my head at the minute and any help would be appreciated. I didn't bother putting the output below as this function isn't really supposed to do anything until a trigger is matched to a current price variable.
BTW, the thread function below has no problem reading globals set when its initiated, just if I change them in the Pycharm console. I'm leaning to it being a console problem but maybe someone can set me straight.

import time
import threading

the_watcher_flag = 0 # external flag to terminate the_watcher_thread
current_price = 0.0 # this is updated by a websocket client thread that's working fine
current_price_last_update_time # same as above
ws = "" # this is the web socket thread opened earlier in code 
trigger_storage = {} # dict of price floats set as triggers for below function

# below line starts the thread
the_watcher_thread = threading.Thread(target=the_watcher())

def the_watcher():
    global the_watcher_flag
    global current_price
    global current_price_last_update_time
    global ws
    global trigger_storage

    watcher_count = 0
    last_restart = time.time() + 3600 # if your wondering clocks have gone forward here and 3600 is 1 hour

    while True:

        time.sleep(15)
        now_time = time.time() + 3600
        watcher_count = watcher_count + 1

        if the_watcher_flag == 1: # problem, this thread seems unable to recognize a change in global the_watcher_flag
            print('The watcher is turning off!') # this never prints
            return # this doesn't return from function and quietly close thread 

        if watcher_count == 40: # this if statement, was used to see what was happening and is not needed
            print('The watcher has been running for 10 more minutes!', the_watcher_flag, current_price, end=" ")
            print(time.strftime('%d-%m-%Y %H:%M:%S', time.gmtime(now_time)))
            watcher_count = 0

        if now_time >= (last_restart + 300.0):

            if now_time >= (current_price_last_update_time + 300.0):
                print("Current_price hasn't updated in 5 minutes, closing Web Socket thread for restart!")
                ws_close(ws)
                time.sleep(1)
                print('Opening new Web Socket thread')
                ws = _thread.start_new_thread(ws_thread, ())
                last_restart = time.time() + 3600

        position = 1
        position_s = f"{position:02d}"

        while position <= 50:

            if position == 51:
                break

            if trigger_storage['wait_position' + position_s] == 0.0 \
                    and trigger_storage['buy_position' + position_s] == 0.0 \
                    and trigger_storage['sell_position' + position_s] == 0.0:
                break

            if trigger_storage['wait_position' + position_s] <= current_price \
                    and trigger_storage['wait_position' + position_s] != 0.0:

                print('Trigger detected! > ', trigger_storage['wait_position' + position_s])
                print('Calling buy manager!')
                buy_manager()

            if trigger_storage['buy_position' + position_s] >= current_price \
                    and trigger_storage['buy_position' + position_s] != 0.0:

                print('Trigger detected! > ', trigger_storage['buy_position' + position_s])
                print('Calling the inspector!')
                order_inspector()

            if trigger_storage['sell_position' + position_s] <= current_price \
                    and trigger_storage['sell_position' + position_s] != 0.0:
                print('Trigger detected! > ', trigger_storage['sell_position' + position_s])
                print('Calling the sell manager!')
                sell_manager()

            position = position + 1
            position_s = f"{position:02d}"
I think I have figured it out myself.
I shouldn't have gone into pycharm expecting the console to function the same as what I was using before.
I should have read up on the workings of pycharm.

After implementing a function in the code that changed the flag to terminate the thread it all worked as expected.
After letting the script reach end of file though, inputting a change of variables is not recognized by the still running threads.
Line 11: you do realise that you're calling the_watcher on the main thread and that you're passing its return value as the value for target, right? Think about it, you want the function to run on a separate thread, so you pass the function itself, rather than calling it and passing its return value.