0

I'm creating a script that is posting a message to both discord and twitter, depending on some input. I have to methods (in separate .py files), post_to_twitter and post_to_discord. What I want to achieve is that both of these try to execute even if the other fails (e.g. if there is some exception with login).

Here is the relevant code snippet for posting to discord:

def post_to_discord(message, channel_name):
    client = discord.Client()

    @client.event
    async def on_ready():
        channel = # getting the right channel
        await channel.send(message)
        await client.close()

    client.run(discord_config.token)

and here is the snippet for posting to twitter part (stripped from the try-except blocks):

def post_to_twitter(message):
    auth = tweepy.OAuthHandler(twitter_config.api_key, twitter_config.api_key_secret)
    auth.set_access_token(twitter_config.access_token, twitter_config.access_token_secret)
    api = tweepy.API(auth)
    api.update_status(message)

Now, both of these work perfectly fine on their own and when being called synchronously from the same method:

def main(message):
    post_discord.post_to_discord(message)
    post_tweet.post_to_twitter(message)

However, I just cannot get them to work concurrently (i.e. to try to post to twitter even if discord fails or vice-versa). I've already tried a couple of different approaches with multi-threading and with asyncio. Among others, I've tried the solution from this question. But got an error No module named 'IPython'. When I omitted the IPython line, changed the methods to async, I got this error: RuntimeError: Cannot enter into task <ClientEventTask state=pending event=on_ready coro=<function post_to_discord.<locals>.on_ready at 0x7f0ee33e9550>> while another task <Task pending name='Task-1' coro=<main() running at post_main.py:31>> is being executed..

To be honest, I'm not even sure if asyncio would be the right approach for my use case, so any insight is much appreciated. Thank you.

Piotr
  • 1
  • 3
  • Have you searched for a Python multithreading intoduction/tutorial? You could also consider using Python's async methods. In any case, those two things are similar, but don't mix them for a start, you'll only get more complexity than either topic alone. For context, please also take the [tour] and read [ask]. – Ulrich Eckhardt Dec 04 '21 at 19:07

1 Answers1

0

In this case running the two things in completely separate threads (and completely separate event loops) is probably the easiest option at your level of expertise. For example, try this:

import post_to_discord, post_to_twitter
import concurrent.futures

def main(message):
    with concurrent.futures.ThreadPoolExecutor() as pool:
        fut1 = pool.submit(post_discord.post_to_discord, message)
        fut2 = pool.submit(post_tweet.post_to_twitter, message)
    # here closing the threadpool will wait for both futures to complete

    # make exceptions visible
    for fut in (fut1, fut2):
        try:
            fut.result()
        except Exception as e:
            print("error: ", e)
user4815162342
  • 141,790
  • 18
  • 296
  • 355