十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專(zhuān)業(yè)推廣+無(wú)憂售后,網(wǎng)站問(wèn)題一站解決
隨著業(yè)務(wù)的飛速發(fā)展,API接口越來(lái)越多,路由管理文件從幾十號(hào)變成幾百上千行,且每次上新服務(wù),需要在修改路由文件代碼,帶來(lái)一定的風(fēng)險(xiǎn)。
創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括歷城網(wǎng)站建設(shè)、歷城網(wǎng)站制作、歷城網(wǎng)頁(yè)制作以及歷城網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃等。多年來(lái),我們專(zhuān)注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,歷城網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到歷城省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
制定對(duì)應(yīng)規(guī)則,路由通過(guò)API文件名根據(jù)一定的規(guī)則對(duì)應(yīng)類(lèi)名,然后自動(dòng)導(dǎo)入對(duì)應(yīng)實(shí)現(xiàn)類(lèi),注冊(cè)到Web框架中。
下面這套規(guī)則只是其中一種方案,可以針對(duì)項(xiàng)目情況制定對(duì)應(yīng)的規(guī)則,然后實(shí)現(xiàn)相關(guān)代碼,但是整體思路基本一樣。
代碼目錄結(jié)構(gòu),列一下簡(jiǎn)單的項(xiàng)目文件目錄,下面以flask框架為例:
app.py是啟動(dòng)文件。
resources是API接口代碼文件夾。
services是為API接口服務(wù)的函數(shù)封裝文件夾。
如果項(xiàng)目還有依賴文件,也可以單獨(dú)再建其他文件夾。
項(xiàng)目的API接口代碼均放在resources文件夾下,且此文件夾只能寫(xiě)接口API服務(wù)代碼。
接口名稱命名以_連接單詞,而對(duì)應(yīng)文件里的類(lèi)名文件名稱的單詞,不過(guò)換成是駝峰寫(xiě)法。
規(guī)則舉例如下:
如上圖,resources下有一個(gè)hello_world接口,還有一個(gè)ab項(xiàng)目文件夾,ab下面還有一個(gè)hello_world_python接口以及子項(xiàng)目文件夾testab, testab下面也有一個(gè)hello_world_python.
接口文件的文件名命名規(guī)范:
文件名命名均為小寫(xiě),多個(gè)單詞之間使用'_'隔開(kāi),比如hello_world.py 命名正確,helloWorld.py命名錯(cuò)誤。


路由入口文件會(huì)自動(dòng)映射,映射規(guī)則為:
前綴 / 項(xiàng)目文件夾[...] / 文件名
其中 前綴為整個(gè)項(xiàng)目的路由前綴,可以定義,也可以不定義,比如api-ab項(xiàng)目,可以定義整個(gè)項(xiàng)目的路由前綴為 ab/
resource下面項(xiàng)目文件夾如果有,則會(huì)自動(dòng)拼接,如果沒(méi)有,則不會(huì)讀取。
舉例:
前綴為空,上圖resources中的三個(gè)接口對(duì)應(yīng)的路由為:
hello_world.py ==> /hello_world
ab/hello_world_python.py ==> /ab/hello_world_python
ab/testab/hello_world_python.py ==> /ab/testab/hello _world_python前綴為ab/,上圖resources中的三個(gè)接口對(duì)應(yīng)的路由為:
hello_world.py ==> ab/hello_world
ab/hello_world_python.py ==> ab/ab/hello_world_python
ab/testab/hello_world_python.py ==> ab/ab/testab/hello_world_pythonpython很多框架的啟動(dòng)和路由管理都很類(lèi)似,所以這套規(guī)則適合很多框架,測(cè)試過(guò)程中有包括flask, tornado, sanic, japronto。 以前年代久遠(yuǎn)的web.py也是支持的。
完整代碼地址:
https://github.com/CrystalSkyZ/PyAutoApiRoute
實(shí)現(xiàn)下劃線命名 轉(zhuǎn) 駝峰命名 函數(shù),代碼演示:
def underline_to_hump(underline_str):
'''
下劃線形式字符串轉(zhuǎn)成駝峰形式,首字母大寫(xiě)
'''
sub = re.sub(r'(_\w)', lambda x: x.group(1)[1].upper(), underline_str)
if len(sub) > 1:
return sub[0].upper() + sub[1:]
return sub實(shí)現(xiàn)根據(jù)字符串導(dǎo)入模塊函數(shù), 代碼演示:
通過(guò)python內(nèi)置函數(shù)__import__函數(shù)實(shí)現(xiàn)加載類(lèi)
def import_object(name):
"""Imports an object by name.
import_object('x') is equivalent to 'import x'.
import_object('x.y.z') is equivalent to 'from x.y import z'.
"""
if not isinstance(name, str):
name = name.encode('utf-8')
if name.count('.') == 0:
return __import__(name, None, None)
parts = name.split('.')
obj = __import__('.'.join(parts[:-1]), None, None, [parts[-1]], 0)
try:
return getattr(obj, parts[-1])
except AttributeError:
raise ImportError("No module named %s" % parts[-1])importlib.import_module(name)上面2種方法都可以,github上代碼里2種方法都有測(cè)試。
檢索resources文件夾,生成路由映射,并導(dǎo)入對(duì)應(yīng)實(shí)現(xiàn)類(lèi), 代碼演示如下:
def route(route_file_path,
resources_name="resources",
route_prefix="",
existing_route=None):
route_list = []
def get_route_tuple(file_name, route_pre, resource_module_name):
"""
:param file_name: API file name
:param route_pre: route prefix
:param resource_module_name: resource module
"""
nonlocal route_list
nonlocal existing_route
route_endpoint = file_name.split(".py")[0]
#module = importlib.import_module('{}.{}'.format(
# resource_module_name, route_endpoint))
module = import_object('{}.{}'.format(
resource_module_name, route_endpoint))
route_class = underline_to_hump(route_endpoint)
real_route_endpoint = r'/{}{}'.format(route_pre, route_endpoint)
if existing_route and isinstance(existing_route, dict):
if real_route_endpoint in existing_route:
real_route_endpoint = existing_route[real_route_endpoint]
route_list.append((real_route_endpoint, getattr(module, route_class)))
def check_file_right(file_name):
if file_name.startswith("_"):
return False
if not file_name.endswith(".py"):
return False
if file_name.startswith("."):
return False
return True
def recursive_find_route(route_path, sub_resource, route_pre=""):
nonlocal route_prefix
nonlocal resources_name
file_list = os.listdir(route_path)
if config.DEBUG:
print("FileList:", file_list)
for file_item in file_list:
if file_item.startswith("_"):
continue
if file_item.startswith("."):
continue
if os.path.isdir(route_path + "/{}".format(file_item)):
recursive_find_route(route_path + "/{}".format(file_item), sub_resource + ".{}".format(file_item), "{}{}/".format(route_pre, file_item))
continue
if not check_file_right(file_item):
continue
get_route_tuple(file_item, route_prefix + route_pre, sub_resource)
recursive_find_route(route_file_path, resources_name)
if config.DEBUG:
print("RouteList:", route_list)
return route_list以flask框架為例,其余框架請(qǐng)看github中的代碼演示。
app.py 中代碼
app = Flask(__name__)
api = Api(app)
# APi route and processing functions
exist_route = {"/flask/hello_world": "/hello_world"}
route_path = "./resources"
route_list = route(
route_path,
resources_name="resources",
route_prefix="flask/",
existing_route=exist_route)
for item in route_list:
api.add_resource(item[1], item[0])
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(parse_args.port), debug=config.DEBUG)運(yùn)行app.py之后,路由打印如下:
RouteList: [
('/hello_world', ),
('/flask/ab/testab/hello_world_python_test', \
),
('/flask/ab/hello_world_python', )
] 元組第一個(gè)元素則是路由,第二個(gè)元素是對(duì)應(yīng)的實(shí)現(xiàn)類(lèi)。
總結(jié):
至此,通過(guò)制定一定規(guī)則,解放路由管理文件方案完成。 歡迎各位一起討論其余比較好的方案,更多方案討論可以關(guān)注微信公眾號(hào): 天澄的技術(shù)筆記 。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。