3
\$\begingroup\$

I'm fairly new to Python - though not new to programming by any means. I have this Python script and it works perfect for my needs but being new(er) to Python I'm just looking to see if there are any general things I could be doing better or 'more Python-esque'. I recently refactored all of this into what you see now - it used to be one long script. It's now separated out into logical methods. But I know all too well that code can ALWAYS be cleaner. So, any tips or things that could be improved?

Side note: I changed the file paths/Twitter authentication tokens/etc for security purposes but the rest of the code is untouched.

import tweepy
import pytz
import os

idfile = '/pathtofile/tweet_lastID.txt'

def get_tweets():
    '''
    Sets up and returns the twitter api.
    '''
    consumerKey = 'consumerKey'
    consumerKeySecret = 'consumerKeySecret'
    accessToken = 'accessToken'
    accessTokenSecret = 'accessTokenSecret'
    auth = tweepy.OAuthHandler(consumerKey, consumerKeySecret)
    auth.set_access_token(accessToken, accessTokenSecret)
    return tweepy.API(auth).user_timeline('mytwitterhandle', since_id=get_last_id_from_file())

def get_last_id_from_file():
    '''
    Gets the id of the last downloaded tweet from the id file.
    '''
    with open(idfile, 'r') as f:
        return f.readline().rstrip()

def update_last_id(tweets):
    '''
    Updates the id file with the latest id.
    '''
    if not tweets:
        return

    for tweet in reversed(tweets):
        latestID = tweet.id_str

    with open(idfile, 'w') as f:
        f.write(latestID + '\n')

def write_tweets_to_file(tweets):
    '''
    Writes the given tweets to the backup file.
    '''
    if not tweets:
        return

    doc_path = '/pathtofile/tweets_backup.txt'
    with open(doc_path, 'a') as f:
        for tweet in reversed(tweets):
            f.write('\n'.join(tweet).encode('utf8'))

def format_date(date):
    '''
    Formats a given date to the format '%-d %b %Y at %-I:%M%p'.
    '''
    datefmt = '%-d %b %Y at %-I:%M%p'
    homeTZ = pytz.timezone('US/Central')
    utc = pytz.utc

    ts = utc.localize(date).astimezone(homeTZ)
    timeString = ts.strftime(datefmt)
    timeOfDay = timeString[len(timeString)-2:]
    timeString = timeString[:-2]
    return timeString + timeOfDay[:-1].lower()

def make_tweet(tweet):
    '''
    Returns a formatted tweet to be written to the backup file from the given tweet data.
    '''
    return [format_date(tweet.created_at), tweet.text, '----------\n']

if __name__ == '__main__':
    tweets = get_tweets()
    new_tweets = []

    for tweet in tweets:
        new_tweets.extend([make_tweet(tweet)])

    write_tweets_to_file(new_tweets)
    update_last_id(tweets)
\$\endgroup\$
2
\$\begingroup\$

The code is more 'Pythonic' than the majority of the codes I have seen here. Are you sure you are just a beginner in python?

One suggestion is to keep consumerKey, consumerKeySecret, accessToken and accessToken secret in another python file, and import these values from that file. If you do that then, when you need to send this code to somebody or upload it anywhere, you can do it without worrying about making your consumerKey, consumerKeySecret, accessToken and accessToken values public.

Some of your lines are too long. I recommend you to follow PEP 8 standards while writing the code.

Also keep the naming convention uniform throughout the code.If you are using camelcase, then follow camelcase throughout.

I believe that you can do the following task

for tweet in reversed(tweets):
    latestID = tweet.id_str

like this:

lastID = tweet[0]

Also you are appending the tweets into a file and get_last_id() returns the topmost tweet id. I think that is a bug.

A class for each Tweet would have been better. That will make the code more beautiful.

Here is my implementation: github. You can refer it while converting this into a class. PS: My code is also not perfect. So I also welcome any comments, tips on my code too.

\$\endgroup\$
  • \$\begingroup\$ lastID = tweets[0] won't work, tweets is a lazy iterator function if I recall the tweepy api. though lastID = tweets.next() should do the trick \$\endgroup\$ – megawac May 19 '14 at 4:48
  • \$\begingroup\$ Wow, thanks for all the great tips! 1. Keeping the keys in a separate file is a great idea. 2. I think I'm too used to an IDE formatting my code for me and I am just using a regular text editor to write this code so my lines are probably too long. 3. Haha there's my Java background for you. I'll fix the camel case. 4. I'll see if there's a better way to get the last id from the list of tweets. 5. If you'll notice, I'm using 2 files - one to hold the last id and one to hold all of the tweets. 6. I'll look into making a Tweet class, though I'm not exactly sure what you mean by that. \$\endgroup\$ – Matthew Janssen May 19 '14 at 12:39
  • \$\begingroup\$ To get the latest tweet you could just break after the first iteration of for tweet in tweets: \$\endgroup\$ – BeetDemGuise May 21 '14 at 19:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.