Forums

Twitter API authenticates from bash, fails from scheduled task

I am trying to get my free account to authenticate to Twitter, as part of a scheduled task. It works on my local computer, and on PA from bash.

I think I have taken care of the working directory / file directory issue.

It seems to be failing when attempting to get the URL from Twitter for authentication purposes.

I have a more detailed question on SO from a code / error perspective, but for PA purposes, my main question is: any reason this should be happening / is intentional behaviour? Am I hitting some endpoints that aren't whitelisted for free accounts? Am I not able to authenticate because I'm restricted to outbound-only traffic and thus Twitter can't send me the URL? Any ideas?

The question on SO: https://stackoverflow.com/questions/66109751/pythonanywhere-twitter-api-authenticates-from-bash-but-fails-on-scheduled-task

ah! just to double check-- while you do have the environment variables setup for local / bash-- do you have it setup for your scheduled task?

@conrad: not sure if this answers the question, but I'm using os.getenv. Do I need to do something outside of my script to get the environment set up for scheduled tasks, where I don't have to do that for bash? My config.py file is below, and it works when I execute it via bash console on the PA servers.

Is there a reason the below script wouldn't retrieve the environment when running with a scheduled task, but it would from the PA bash?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/python3.8

import twitter
import os
import logging
from dotenv import load_dotenv

logger = logging.getLogger()

# project folder is one level up from file location
project_folder = pathlib.Path(__file__).parent.absolute()
load_dotenv(os.path.join(project_folder, '.env'))

# Authenticate to Twitter and create API object
TWITTER_CONSUMER_API_KEY = os.getenv("TWITTER_CONSUMER_API_KEY")
TWITTER_CONSUMER_API_SECRET = os.getenv("TWITTER_CONSUMER_API_SECRET")

TWITTER_ACCESS_TOKEN = os.getenv("TWITTER_ACCESS_TOKEN")
TWITTER_ACCESS_SECRET = os.getenv("TWITTER_ACCESS_SECRET")

def create_api():

    # Create API object
    api = twitter.Api(
        access_token_key = TWITTER_ACCESS_TOKEN,
        access_token_secret = TWITTER_ACCESS_SECRET,
        consumer_key = TWITTER_CONSUMER_API_KEY,
        consumer_secret = TWITTER_CONSUMER_API_SECRET,
        sleep_on_rate_limit=True)

    # test API object
    if api.VerifyCredentials():
        pass
    else:
        logger.error("Error creating API", exc_info=True)
        raise Exception("Twitter user authentication error")

    logger.info("API created")
    return api

ah I meant to say just print each of TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_SECRET etc and make sure that they are the correct values?

@conrad: Thank you! Seems to work now. Not exactly sure what made the difference, but I tried what you suggested, moved some things around, and it's working :)