Search code examples
pythongithubgithub-actions

Github Actions - Passing value from one Python script to another


I'm in the earlier stages of learning Python, and have run into a problem with my first project.

For context, I am creating an application that sends an email every day with a few sentences from a specific Wikipedia page. For example, a user will get the summary of the Wikipedia article for "The New York Times". Each day, an email is sent on a new Wikipedia topic. The goal is to have the person learn about a new topic each day via email.

My code runs well on my local environment. But I needed to deploy the application to ensure that the emails were sent daily even when my computer was off. For this, I'm using Github Actions to run my files at a scheduled time every day.

In terms of specifics, I have a Python file, File1.py, that has a few pre-loaded Wikipedia topics. It runs through the first 10 sentences of one of the pre-loaded Wikipedia topics using the Wikipedia API and sends those sentences out in an email. It then updates the "counter" variable in the second python script, File2.py, and exits.

The purpose of this is to make sure that File1.py starts at the next ten sentences of the Wikipedia topic. Or to move onto the next topic if one is done.

That being said, I can't figure out how to run this correctly from Github. The YAML file is executing correctly and running File1.py, the email is being sent out on schedule, but File2.py, which contains the counter variable, is not being updated. This is the problem. If there is a better way to do this without writing to File2.py, please let me know.

Here is part of File1.py


# # Iterates over the sentences
while True:

    for j in range(len(listOfTopics)):
        
        # When a new page starts, set counter to 0 again
        new_value = 0

        with open(r'File2.py', 'w') as f:
            f.write(f"counter={new_value}")
            f.flush()
            f.close()

        initialPage = wikipedia.page(listOfTopics[j])
        totalContent = initialPage.content
        sentences = sent_tokenize(totalContent) # Breaking down the content into sentences
        
        tenSentences = []

        for i in range(counter, len(totalContent)):

            tenSentences.append(sentences[i])
            if len(tenSentences) == 10:
                server.sendmail('[email protected]', '[email protected]', \
     f"Subject: Topics Email.\n{tenSentences}".encode('utf-8'))
                
                tenSentences = []

                # Iterating through next ten sentences by changing the counter variable
                new_value = counter + 10 

                with open(r'File2.py', 'w') as f:
                    f.write(f"counter={new_value}")
                    f.flush()
                    f.close()

                sys.exit()

And here is File2.py

counter=10

Solution

  • Why it doesn't work?

    Every time you run your workflow, it starts with a new environment. Though youd didn't share your workflow file I assume that one of steps is checkout.

    This means this is what happens every time:

    1. Some condition occurs (it's scheduled)
    2. You checkout your code (with counter=10)
    3. You run your code (now counter=11)
    4. Environment is cleaned up (there is no counter at all)

    So there are two solutions that come to my head:

    Solution 1: Easy, not orthodox

    This solution is what you expect. Just commit counter=11 after 3rd step. This will change your counter checked in 1st step. There are few answers on how to do it in github actions

    Solution 2: Harder, more elegant

    This solution requires much more work, but its more... production ready. This counter could be served externally. I mean available from some API or maybe database connection?

    Din't try this, but there is some free CountAPI

    Why second one is better?

    • no race condition - If you run your script twice fast - you'll two times couter=11 commits. With atomic API you should get counter=11 and counter=12.
    • clean - you separate data from code