2015-08-28 59 views
0

我只是想知道Python的行爲以及它是如何工作的。我有一個腳本來運行並收集所有追隨者和帳戶的朋友。爲什麼Python每次都在__main__之外運行代碼?

這是代碼。

#!/usr/bin/env python 
import pymongo 
import tweepy 

from pymongo import MongoClient 

from sweepy.get_config import get_config 

config = get_config() 

consumer_key = config.get('PROCESS_TWITTER_CONSUMER_KEY') 
consumer_secret = config.get('PROCESS_TWITTER_CONSUMER_SECRET') 
access_token = config.get('PROCESS_TWITTER_ACCESS_TOKEN') 
access_token_secret = config.get('PROCESS_TWITTER_ACCESS_TOKEN_SECRET') 

MONGO_URL = config.get('MONGO_URL') 
MONGO_PORT = config.get('MONGO_PORT') 
MONGO_USERNAME = config.get('MONGO_USERNAME') 
MONGO_PASSWORD = config.get('MONGO_PASSWORD') 

client = MongoClient(MONGO_URL, int(MONGO_PORT)) 

print 'Establishing Tweepy connection' 

auth = tweepy.OAuthHandler(consumer_key, consumer_secret) 
auth.set_access_token(access_token, access_token_secret) 
api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True, retry_count=3) 

db = client.tweets 
db.authenticate(MONGO_USERNAME, MONGO_PASSWORD) 

raw_tweets = db.raw_tweets 
users = db.users 

def is_user_in_db(screen_name): 
    return get_user_from_db(screen_name) is None 

def get_user_from_db(screen_name): 
    return users.find_one({'screen_name' : screen_name}) 

def get_user_from_twitter(user_id): 
    return api.get_user(user_id) 

def get_followers(screen_name): 
    users = [] 
    for i, page in enumerate(tweepy.Cursor(api.followers, id=screen_name, count=200).pages()): 
     print 'Getting page {} for followers'.format(i) 
     users += page 
    return users 

def get_friends(screen_name): 
    users = [] 
    for i, page in enumerate(tweepy.Cursor(api.friends, id=screen_name, count=200).pages()): 
     print 'Getting page {} for friends'.format(i) 
     users += page 
    return users 

def get_followers_ids(screen_name): 
    ids = [] 
    for i, page in enumerate(tweepy.Cursor(api.followers_ids, id=screen_name, count=5000).pages()): 
     print 'Getting page {} for followers ids'.format(i) 
     ids += page 

    return ids 

def get_friends_ids(screen_name): 
    ids = [] 
    for i, page in enumerate(tweepy.Cursor(api.friends_ids, id=screen_name, count=5000).pages()): 
     print 'Getting page {} for friends ids'.format(i) 
     ids += page 
    return ids 

def process_user(user): 
    screen_name = user['screen_name'] 

    print 'Processing user : {}'.format(screen_name) 

    if is_user_in_db(screen_name): 
     user['followers_ids'] = get_followers_ids(screen_name) 
     user['friends_ids'] = get_friends_ids(screen_name) 

     users.insert_one(user) 
    else: 
     print '{} exists!'.format(screen_name) 

    print 'End processing user : {}'.format(screen_name) 

if __name__ == "__main__": 

    for doc in raw_tweets.find({'processed' : {'$exists': False}}): 
     print 'Start processing' 
     try: 
      process_user(doc['user']) 
     except KeyError: 
      pass 

     try: 
      process_user(doc['retweeted_status']['user']) 
     except KeyError: 
      pass 

     raw_tweets.update_one({'_id': doc['_id']}, {'$set':{'processed':True}}) 

我把什麼從日誌中得到的是

Rate limit reached. Sleeping for: 889 
Establishing Tweepy connection 
Start processing 
Processing user : littleaddy80 
Establishing Tweepy connection 
Start processing 
Processing user : littleaddy80 
Establishing Tweepy connection 
Start processing 
Processing user : littleaddy80 
Establishing Tweepy connection 
Start processing 
Processing user : littleaddy80 
Rate limit reached. Sleeping for: 891 

我不知道,因爲Establishing Tweepy connection__main__以外,它不應該被一遍又一遍的運行。我只是想知道爲什麼Python的行爲如此,或者我的代碼中存在錯誤?

+4

Python在文件中逐行運行_everything_,這是'__main__'後衛的要點。 – bereal

+0

它看起來更像是你的腳本正在退出並被某些東西重新啓動; 「建立Tweepy連接」應該只打印一次,無論模塊是否作爲腳本導入或執行。 – chepner

+0

@chepner我使用主管來管理流程。 – toy

回答

0

當您運行/進口則執行它的每一個語句python腳本(但是導入時,這隻會發生第一次導入模塊或當你做reload(module))。有幾個通常可以注意到的語句:

  • 函數定義的執行意味着正在定義函數(不執行函數的主體)。
  • 執行導入語句將導入模塊。
  • 類定義的執行意味着它的主體被執行,大部分它將包含函數定義,所以它主要是定義函數。
  • if語句的執行意味着首先對控制表達式進行評估並根據該正文執行。
  • 分配的執行意味着rhs-expression將被評估爲可能的副作用。

這就是爲什麼通常不會將代碼直接放在python腳本的頂層 - 它會被執行。如果它既可以作爲腳本也可以作爲模塊運行 - 以腳本運行時應該運行的代碼應該包含在if __name__ == '__main__'-語句中。

除非你需要全球變中你的腳本是一堆的函數定義和類定義依次爲:

if __name__ == "__main__": 
    code_to_be_executed_iff_run_as_a_script() 
else: 
    code_to_be_executed_iff_imported() 

,如果您需要全局變量,你將有運行時有時需要特別小心,以避免副作用/導入模塊。

0

如果你想運行只有導入時,它會去的else條款正常__main__後衛代碼:

if __name__ == '__main__': 
    print("Run as a script") 
else: 
    print("Imported as a module") 
+0

如果我想用Tweep建立連接並與腳本中的所有功能共享連接。我如何實現這一目標? – toy

0

這正是個之所以有

if __name__ == "__main__": 

之前這個條件你應該有函數和類定義,並且在它之後,你想運行的代碼。

原因是導入文件時(因爲每個python文件也是可導入的模塊),__name__變量不同,並且運行python myfile.py

創建文件例如myfile.py

# content of myfile.py 
print(__name__) 

當你運行它,它會打印__main__

$ python myfile.py 
__main__ 

但在導入過程中它所攜帶的進口模塊(myfile)的名稱。

$ python 
>>> import myfile 
myfile 
相關問題