前言
aardio中有些經常使用的庫,換個專案總需要複製一下,還不便於修改。雖然可以直接把它放到aardio\lib
目錄下,也是不便於共享給其他人使用。
最近偶然翻到編輯器裡的工具
->開發環境
->擴充套件庫釋出工具
,就想著可以像官方一樣,釋出自己的擴充套件庫,也便於分享給大家使用,最好能像官方擴充套件庫一樣線上安裝。
閱讀官方程式碼
翻了一下程式碼,其實官方擴充套件庫的邏輯也很簡單,先請求一遍所有擴充套件庫列表,這是個json檔案。
裡面包含擴充套件庫的基本資訊和下載的url,下載的格式是.tar.lzma
,而上面的擴充套件庫釋出工具就是將庫打包成這個格式。
當你要安裝某個庫時,就會把它下載並解壓到aardio\lib
資料夾下。
寫好的成品
下面是我弄的擴充套件庫,目前庫只有幾個,基本都是我最近才寫的,有興趣的可以去github下載測試下bug。
歡迎大家共享一些常用庫,減少造輪子的時間。
開源地址
搭建的程式碼放到github了,你可以簡單的修改程式碼裡面的倉庫地址來做一個自己的擴充套件倉庫
github:https://github.com/kanadeblisst00/aardio-extlibs
github的訪問國內偶爾會抽風,所以我擴充套件庫裡的下載地址放的是國內伺服器搭建的映象倉庫(它會每10分鐘同步上面github的資料)
國內加速倉庫: http://git.pygrower.cn/kanadeblisst/aardio-extlibs
使用方法
先下載extlibs.aardio
這個檔案到本地(只需要這個檔案,其他都是打包的程式碼,這個是下載的程式碼)
把它重新命名為5.extlibs.aardio
,移動到aardio\tools
資料夾下,該目錄下還有個1.ext.aardio
檔案,這是官方擴充套件庫。
接著重新開啟aardio的編輯器,就可以在工具裡看到有個非官方擴充套件庫
。使用方法和上面的擴充套件庫是一樣的,執行它選擇需要安裝的庫,它就會下載好放到aardio\lib
目錄下
搭建教程
上面的倉庫裡的程式碼就是搭建的全部程式碼。這裡我簡單的說一下這些程式碼流程
目錄結構
- dist: 打包後的檔案,用於在
extlibs.aardio
裡遠端下載安裝 - lib: 庫程式碼
- res: 庫的使用案例
- main.aardio: 將lib下的庫打包壓縮到dist裡
搭建步驟
將你需要打包的庫放在lib目錄下,然後開啟這個專案並執行。它會將lib下的所有庫打包成tar檔案放在dist\package
目錄下。
還會將res目錄存放的案例打包成zip放到dist\samples
下,同時生成庫的json資訊。而dist\exlibs.json
是所有庫的彙總資訊。
格式如下:
{
"goquery":{
"author":"kanadeblisst",
"description":"goquery封裝庫,用於解析HTML",
"url":"http://git.pygrower.cn/kanadeblisst/aardio-extlibs/raw/branch/master/dist/package/goquery.tar.lzma",
"version":"1.0.0.1",
"weight":1
}
}
後面只需把專案程式碼(extlibs.aardio
和main.aardio
)裡的git地址換成你自己的git地址
thread.set("GithubRepo", "http://git.pygrower.cn/kanadeblisst/aardio-extlibs");
具體流程
執行了專案之後就會在dist目錄下生成需要的檔案,而這些檔案都可以透過連結直接訪問到。
比如exlibs.json
的連結就是倉庫地址+ /raw/branch/master/dist/exlibs.json
,這樣就能下載到所有的庫資訊,然後把它顯示到介面。
下載的函式只需要在ide.requestLibInfo
這個庫函式基礎上修改下url,程式碼如下
var requestLibInfo = function(libName){
return ..thread.invokeAndWait(
function(libName){
import web.rest.jsonLiteClient;
var repoUrl = thread.get("GithubRepo");
var url = repoUrl + "/raw/branch/master/dist/exlibs.json";
var http = web.rest.jsonLiteClient(null,"");
var libApi = http.api(url)
var listLib = libApi.get();
http.close();
var lib;
if(libName){
lib = listLib[libName];
lib["libName"] = libName;
}else{
lib = listLib;
}
return lib;
},libName
)
};
requestLibInfo
官方使用的ide.requestLibInfo
來下載庫資訊。但url是在函式里寫死的,我並不想修改ide這個庫的程式碼,又想讓這個函式去我指定的連結下載庫資訊,怎麼操作最方便?
最先想到的肯定是將var libs = ide.requestLibInfo();
改成var libs = requestLibInfo();
,我不用它就行了。
但有個問題ide.installLib
方法也被使用了,而且還呼叫了ide.requestLibInfo
,難道又要重寫installLib
?
偷懶的修改方式
當然不用,修改的話很簡單,只需要多加一行程式碼:
import ide;
ide.requestLibInfo = requestLibInfo;
var libs = ide.requestLibInfo();
新增了ide.requestLibInfo = requestLibInfo;
這行程式碼後,在ide.installLib
裡呼叫的ide.requestLibInfo
也會被替換成我的函式。
這樣就只多了一行程式碼,不用去重寫多個函式。如果在多執行緒使用的話,同樣需要新增這行程式碼。
hook
上面這個思路其實很常見,專業名詞的話是hook。比如我之前寫的Python呼叫ocr,有人提了個需求:https://github.com/kanadeblisst00/wechat_ocr/issues/6
這個需求很小眾,根本不用去修改庫程式碼來實現,只需要hook一下print就能做到:
import builtins
def my_print(*args, **kwargs):
pass
builtins.print = my_print
如果只想過濾某個模組的print,可以透過inspect模組獲取上上層呼叫的函式和所在模組,根據函式名或模組名就能過濾掉指定模組的print列印
import builtins
def caller_info():
# 獲取當前幀的上一幀,即呼叫者的幀
caller_frame = inspect.currentframe().f_back.f_back
# 獲取呼叫者所在的模組和函式
caller_module = inspect.getmodule(caller_frame)
caller_name = caller_frame.f_code.co_name
# 如果能獲取到呼叫者模組,則提取模組名;否則為None
module_name = caller_module.__name__ if caller_module else None
return module_name, caller_name
old_print = builtins.print
def my_print(*args, **kwargs):
module_name, caller_name = caller_info()
if "ocr" not in module_name:
old_print(*args, **kwargs)
builtins.print = my_print
本文由部落格一文多發平臺 OpenWrite 釋出!