歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

Python調(diào)用package時(shí),如何避免循環(huán)引入?

發(fā)布時(shí)間:2017-09-04 20:25  回復(fù):0  查看:2962   最后回復(fù):2017-09-04 20:25  
Python 開發(fā) 中使用package 時(shí),出現(xiàn)循環(huán)導(dǎo)入問題十分常見,我們創(chuàng)建如下 package 來說明這個(gè)問題 :
  pkg
  ├──  __init__.py
  ├──  module_a.py
  └──  module_b.py
  其中,
  ·  __init__.py    pkg  指定為一個(gè)Python package
  ·  module_a.py  中定義了一個(gè)  action_a()  函數(shù),該函數(shù)引用了  module_b.py  中的一個(gè)attribute ,如一個(gè)函數(shù)或變量
  ·  module_b.py  中定義了一個(gè)  action_b()  函數(shù),該函數(shù)引用了  module_a.py  中的一個(gè)attribute ,如一個(gè)函數(shù)或變量
  這種情況下,執(zhí)行該package 時(shí)會(huì)拋出  circular import error  錯(cuò)誤,即循環(huán)引用,因?yàn)?/span>  module_a  試圖去引入  module_b  時(shí),而 module_b  首先要引入  module_a  ,這會(huì)導(dǎo)致Python 解釋器無法執(zhí)行下去。
  然而,我們可以通過一些巧妙的方法,讓上面的邏輯正常工作,同時(shí)避免循環(huán)引入的錯(cuò)誤。
  那么,什么時(shí)候它能正常工作,什么時(shí)候不能正常工作,而那些能夠正常工作的情況又是什么原因呢?
   何時(shí)它能正常工作?
   1. module頂部引入,不要用 from ,相對引入,只在Python 2中有效
  在module 的頂部 import ,如  import another_module  module  中的函數(shù)以  another_module.attribute  的方式引用 another_module  中的函數(shù)或變量等。這種方式之所以有效,是由于  import another_module  是基于當(dāng)前目錄的相對引用,而且是一種隱式引用,如果從另一個(gè)package 中引入 module 時(shí),就可以失效了。另外,  import another_module  這種語法在Python 3  中已經(jīng)不支持了,所以不要在代碼中用這種方法來避免循環(huán)引入。
  如:
  # pkg/ module_a.py  from __future__  import print_function import module_b
   def  action_a():
  print(module_b.action_b.__name__)
  # pkg/ module_b.pyfrom __future__  import print_function import module_a
   def  action_b():
  print(module_a.action_a.__name__)
   2. module的頂部引入,不要用 from ,絕對引入
  在module 的頂部 import ,使用從 package 開始的絕對路徑,如  import package.another_module ,module  中的函數(shù)以 package.another_module.attribute  的方式引用  another_module  中的函數(shù)或變量等。之所以要掛上package name 來引入,是由于 import .another_module  這種形式的相對引入 會(huì)報(bào)語法錯(cuò)誤,而掛上 package 的絕對引入, Python 2 3 都支持
  案例:
  # pkg/ module_a.pyfrom __future__  import print_function import pkg2.module_b
   def  action_a():
  print(pkg2.module_b.action_b.__name__)
  # pkg/ module_b.pyfrom __future__  import print_function import pkg2.module_a
   def  action_b():
  print(pkg2.module_a.action_a.__name__)
   3. module底部引入another moduleattribute,而非another module,用 from
  在module 的底部 import (至少要在被引用的 attribute 之后 import ),直接引入 another module attribute ,如  from package.another_module import attribute  ,相對引入也支持,如  from .another_module import attribute  ,module 中的函數(shù)直接使用被引用的 attribute 即可。
  如:
  # pkg/ module_a.pyfrom __future__  import print_function
   def  action_a():
  print(action_b.__name__)
   from .module_b  import action_b
  # pkg/ module_b.pyfrom __future__  import print_function
   def  action_b():
  print(action_a.__name__)
   from .module_a  import action_a
   4. 函數(shù)頂部引入,可以用 from
  在module 的  function  頂部import ,如  from package import another_module  ,也支持相對引入,引入module attribute 均可。
  如:
  # pkg/ module_a.pyfrom __future__  import print_function
   def  action_a():
   from .  import module_b
  print(module_b.action_b.__name__)
  # pkg/ module_b.pyfrom __future__  import print_function
   def  action_b():
   from .  import module_a
  print(module_a.action_a.__name__)
  或
  # pkg/ module_a.pyfrom __future__  import print_function
   def  action_a():
   from .module_b  import action_b
  print(action_b.__name__)
  # pkg/ module_b.pyfrom __future__  import print_function def  action_b():
   from .module_a  import action_a
  print(action_a.__name__)
  這種方式雖然Python 2 3 都支持,但編碼不夠優(yōu)雅,影響代碼可讀性,不建議使用
  
  ·  本文討論的問題,是 Python 中調(diào)用 package 時(shí),應(yīng)如何避免循環(huán)引入
  ·  當(dāng)直接在命令行執(zhí)行一個(gè) Python module 時(shí),適用情況不完全相同
來源:Gevin 的博客
您還未登錄,請先登錄

熱門帖子

最新帖子

?