Search code examples
pythoninstagrampython-multithreadingschedule

Python, Use threading and schedule to keep running a function constantly


I am making a bot that auto-posts to Instagram using instabot, now the thing is that if I exceed a number of request the bot terminate the script after retrying for some minutes.

The solution I came up with is to schedule the script to run every hour or so, and to ensure that the script will keep running constantly I used threading to restart the posting function when the thread is dead.

The function responsible for posting, in this code if the bot instance from instabot retried sending requests for some minutes and failed, it terminates the whole script.

def main():
    create_db()
    try:
        os.mkdir("images")
        print("[INFO] Images Directory Created")
    except:
        print("[INFO] Images Directory Found")
    # GET A SUBMISSION FROM HOT
    submissions = list(reddit.subreddit('memes').hot(limit=100))
    for sub in submissions:
        print("*"*68)
        url = sub.url
        print(f'[INFO] URL : {url}')
        if "jpg" in url or "png" in url:
            if not sub.stickied:
                print("[INFO] Valid Post")
                if check_if_exist(sub.id) is None:
                    id_ = sub.id
                    name = sub.title
                    link = sub.url
                    status = "FALSE"
                    print(f"""
                                [INFO] ID = {id_}
                                [INFO] NAME = {name}
                                [INFO] LINK = {link}
                                [INFO] STATUS = {status}
                                """)
                    # SAVE THE SUBMISSION TO THE DATABASE
                    insert_db(id_, name, link, status)
                    post_instagram(id_)
                    print(f"[INFO] Picture Uploaded, Next Upload is Scheduled in 60 min")
                    break
    time.sleep(5 * 60)

The scheduling function:

def func_start():
    schedule.every(1).hour.do(main)
    while True:
        schedule.run_pending()
        time.sleep(10 * 60)

And last piece of code:

if __name__ == '__main__':
    t = threading.Thread(target=func_start)
    while True:
        if not t.is_alive():
            t.start()
        else:
            pass

So basically I want to keep running the main function every hour or so, but I am not having any successes.


Solution

  • Looks to me like schedule and threading are overkill for your use case as your script only performs one single task, so you do not need concurrency and can run the whole thing in the main thread. You primarily just need to catch exceptions from the main function. I would go with something like this:

    if __name__ == '__main__':
        while True:
            try:
                main()
            except Exception as e:
                # will handle exceptions from `main` so they do not
                #   terminate the script
                # note that it would be better to only catch the exact
                #   exception you know you want to ignore (rather than
                #   the very broad `Exception`), and let other ones
                #   terminate the script
                print("Exception:", e)
            finally:
                # will sleep 10 minutes regardless whether the last
                #   `main` run succeeded or not, then continue running
                #   the infinite loop
                time.sleep(10 * 60)
    

    ...unless you actually want each main run to start precisely in 60-minute intervals, in which case you'll probably need either threading or schedule. Because, if running main takes, say, 3 to 5 minutes, then simply sleeping 60 minutes after each execution means you'll be launching the function every 63 to 65 minutes.