終于到了看,run.py的時候了.
這篇文章的目的僅僅是初步的了解pyspider,具體作者的寫法,為什么這樣寫,都不在討論的范圍之內(nèi).
我想如果可以的話,以后我也要跟著作者的思路,重新寫一遍pyspider.
read_config(ctx, param, value)
里面有一個underline_dict(d)方法.這個方法返回一個詞典,詞典key的'_'用'-'代替
return dict((k.replace('-', '_'), underline_dict(v)) for k, v in six.iteritems(d))
click會調(diào)用read_config,用來解析參數(shù).其實這里就是讀取了配置文件.
ctx是一個對象,<click.core.Context object at 0x7f8dc6a5be50>,應(yīng)該是只要通過click就會自動生成這樣的對象,具體的我也不了解.
connect_db(ctx, param, value)
讀取出來數(shù)據(jù)庫連接.進(jìn)行連接.這里作者的處理是直接在click接受參數(shù)的時候,直接創(chuàng)建連接
具體代碼暫時不分析.在libs文件夾下面
load_cls(ctx, param, value)
這個函數(shù)之前說過.
從另一個包中導(dǎo)入對象的屬性.這里的對象是廣義的對象,比如,包算一種對象,包里的方法,可以看作屬性.
這個方法主要用在啟動各個組件的時候.比如webui的flask對象,就是通過這個方法導(dǎo)入
connect_rpc
連接到rpc服務(wù).
fetcher和scheduler部分都有生成連接的代碼.具體功能應(yīng)該要到實現(xiàn)組件的代碼里面看
cli(ctx, **kwargs)
這是run的第一個函數(shù),也是入口函數(shù).
因為run的main函數(shù)為
def main():
cli()
if __name__ == '__main__':
main()
ctx是click上下文對象
**kwargs是click通過命令行接受的參數(shù)
這里主要建立以下連接
- taskdb
- projectdb
- resultdb
- data_path
- newtask_queue
- status_queue
- scheduler2fetcher
- fetcher2processor
- processor2result
并且這些連接,全部存在kwargs之中,之后在把kwargs更新到ctx
ctx.obj.update(kwargs) #這里不確定click方法,其實查找click的api,也沒有找到ctx對應(yīng)的對象
之后執(zhí)行
ctx.invoke(all)
開始all方法.
all(ctx,fetcher_num,processor_num,result_worker_num, run_in)
all的代碼很短.特別容易看.
g = ctx.obj
第一步把之前創(chuàng)建的連接和對象賦值給g
之后講各個組建通過線程或者進(jìn)程的方式啟動起來.
#抽出一段fetcher的代碼,其他組件差不多
fetcher_config = g.config.get('fetcher', {})
fetcher_config.setdefault('xmlrpc_host', '127.0.0.1')
for i in range(fetcher_num):
threads.append(run_in(ctx.invoke, fetcher, **fetcher_config))
最后,當(dāng)所有的組件關(guān)閉的時候一次性關(guān)閉.
finally:
# exit components run in threading
for each in g.instances:
each.quit()
# exit components run in subprocess
for each in threads:
if not each.is_alive():
continue
if hasattr(each, 'terminate'):
each.terminate()
each.join()
然后就是各個組建部分的啟動了.
def scheduler(ctx,...)
參數(shù)太長了...
賦值給g.實例化scheduler對象.啟動調(diào)動器
'''
if xmlrpc:
utils.run_in_thread(scheduler.xmlrpc_run, port=xmlrpc_port, bind=xmlrpc_host)
'''
這里的一段代碼現(xiàn)在還不知道怎么回事
def fetcher(ctx, ...)
def phantomjs(ctx,...)
def bench(ctx,...)
def one(ctx,...)
def send_message(ctx, ...)
都差不多