簡體   English   中英

如何強制Python的“導入”將名稱視為模塊,而不是函數?

[英]How to force Python's “import” to treat name as a module, not a function?

我正在使用SymPy,遇到以下問題:

>>> import sympy.utilities.lambdify
>>> sympy.utilities.lambdify
<function lambdify at 0x0000000003802B38>

等等,不應該是sympy.utilities.lambdify是一個模塊嗎?

>>> from sympy.utilities.lambdify import implemented_function
>>> implemented_function
<function implemented_function at 0x0000000003802CF8>
>>> implemented_function.__module__
'sympy.utilities.lambdify'

哦,所以有一個命名沖突。

現在顯然我可以使用implemented_function ,但這不是我的問題。

我的問題是:如何導入sympy.utilities.lambdify 模塊而不是函數

(我在這里只是使用SymPy進行說明。這是否適當的庫使用是不重要的。來源就在這里 。)

實際上,看起來這可以用importlib非常干凈地完成:

import importlib
lamdify = importlib.import_module('sympy.utilities.lambdify')
print lambdify
  <module 'sympy.utilities.lambdify' from 'c:\python-2.7.8-amd64\lib\site-packages\sympy\utilities\lambdify.pyc'>

來自評論的編輯(感謝@Mehrdad):

或者,如果您想避免將模塊名稱放在字符串中,您可以這樣做:

def import_module(lambda_): 
    import importlib; 
    return importlib.import_module('.'.join(lambda_.__code__.co_names)) 

用法: lambdify = import_module(lambda: sympy.utilities.lambdify)

雖然這看起來有點長,對我來說不太清楚。

明顯的不一致是由於lambdify不是一個模塊,它是一個包含多個函數定義的python文件。 在名為bar.py的文件中考慮以下示例:

def foo(): pass

def bar(): pass

然后from bar import bar; print(bar.__module__) from bar import bar; print(bar.__module__)會給你'bar'

可以導入lambdify的原因,就像這是sympy.utilities__init__sympy.utilities

from .lambdify import lambdify

也就是說,在sympy.utilities模塊的lambdify.py文件中,有一個lambdify()的定義,並將其導入sympy.utilities命名空間。 因此,當您導入sympy.utilities ,您可以訪問lambdify。 但是,你仍然可以import定義等功能lambdify.py通過from sympy.utilities.lambdify import ...


您的實際問題是您是否可以導入這樣的模塊。 嗯, 你可以 ,但你可能不應該。 讓我們使用上面的bar.py對情況進行bar.py ,並通過創建__init__py使其成為一個包:

from .bar import bar

將這兩個文件放在名為tmp ,我們得到一個你的場景模型,一個名為tmp的模塊和一個“子模塊” bar (但我不認為它是一個合適的子模塊,缺少__init__.py )。 如果我們導入tmp.bar就會發生同樣的事情,就像在sympy

>>> import tmp
>>> tmp
<module 'tmp' from '/home/user/python/tmp/__init__.py'>
>>> import tmp.bar
>>> tmp.bar
<function bar at 0x7f24426461e0>
>>> tmp.bar.foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'foo'
>>> from tmp.bar import foo
>>> foo
<function foo at 0x7f2442646158>

所以tmp.bar指的是函數而不是模塊。 顯然。 但實際上它也提供了對模塊的訪問,盡管它被同名函數遮蔽了!

讓我們重復上面的內容,但繼續監視sys.modules

>>> import sys
>>> 'tmp' in sys.modules
False
>>> import tmp.bar
>>> tmp.bar
<function bar at 0x7fc833025158>
>>> 'tmp.bar' in sys.modules
True
>>> tmp.bar.foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'foo'
>>> sys.modules['tmp.bar'].foo
<function foo at 0x7fc833020f28>

因此,雖然tmp.bar引用了本地命名空間中的函數,但我們可以通過來自同一導入的sys.modules['tmp.bar']來訪問模塊本身。

只是為了明確:

>>> import sys
>>> import sympy.utilities.lambdify
>>> lambdify_module = sys.modules['sympy.utilities.lambdify']
>>> lambdify_module.implemented_function
<function implemented_function at 0x7fc83183ca60>

這是針對sympy的結構。 請參閱實用程序__init__.py的源代碼的這一

from .lambdify import lambdify

它導入功能 lambdify從本地模塊lambdify ; 那么utilities.lambdify就是這個功能

假設您希望真正導入模塊,而不是函數, lambdify 也許是這樣的,

import os
import imp

import sympy.utilities as mod
sub_mod_name = 'lambdify'
sub_mod_file = '{}.py'.format(sub_mod_name)

mod_loc = os.path.dirname(mod.__file__)
file_ = os.path.join(mod_loc, sub_mod_file)  # Full path for source file
sub_mod = imp.load_source(sub_mod_name, file_)  # Import module from source file

print sub_mod
# <module 'lambdify' from '/usr/local/lib/python2.7/dist-packages/sympy/utilities/lambdify.pyc'>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM