有没有办法访问导入模块对象的父模块?

13
我需要知道是否有一种方法可以从子模块中访问父模块。如果我导入子模块:
from subprocess import types

我有一个问题 - 有没有一些 Python 的魔法可以从 types 模块中访问 subprocess 模块?类似于这样的东西对于类来说 ().__class__.__bases__[0].__subclasses__()

5
你的示例很奇怪-- types实际上是标准的Python types模块。你的导入语句与import types的作用相同,而且在两种情况下types对象将完全相同。 - Sven Marnach
1
subprocess 对于 types 模块并没有任何有意义或有用的“父级”关系。显然,subprocess 已经导入了 types,就像许多其他模块一样导入了 types。你想要做什么? - John Machin
1
我知道types是标准模块,但当我搜索所有子模块时,我在subprocess模块中找到了它。 - jcubic
@John 我试图阻止对文件系统和 shell 的访问。 - jcubic
@jcubic 如果您仍在生产中使用此项目,请停止用户访问它。如果这能说服您,我将跳出您所创建的沙盒。我可以从完全没有内置函数的沙盒中跳出来,只允许使用文字常量。 - wizzwizz4
1
@wizzwizz4,我是几年前通过一次惨痛的经历学到的教训。有人在我的共享主机上擦除了硬盘。这是为了我的https://trypython.jcubic.pl/网站。我不得不将其禁用,但几年后我发现了js中的brython库,现在我使用这个库。 - jcubic
5个回答

7

如果您已经访问了一个模块,通常可以从sys.modules字典中获取它。Python不会保留名称的“父指针”,特别是因为关系不是一对一的。例如,使用您的示例:

>>> from subprocess import types
>>> types
<module 'types' from '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/types.pyc'>
>>> import sys
>>> sys.modules['subprocess']
<module 'subprocess' from '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.pyc'>

如果你注意到subprocess模块中存在types,那只是因为在其中有import types语句。如果你需要该模块,只需import types即可。
实际上,未来版本的subprocess可能不再导入types,这将导致你的代码出现错误。你应该只导入模块中出现在__all__列表中的名称;其他名称视为实现细节。
例如:
>>> import subprocess
>>> dir(subprocess)
['CalledProcessError', 'MAXFD', 'PIPE', 'Popen', 'STDOUT', '_PIPE_BUF', '__all__', '__builtins__', '__doc__',
 '__file__', '__name__', '__package__', '_active', '_cleanup', '_demo_posix', '_demo_windows', '_eintr_retry_call',
 '_has_poll', 'call', 'check_call', 'check_output', 'errno', 'fcntl', 'gc', 'list2cmdline', 'mswindows', 'os',
 'pickle', 'select', 'signal', 'sys', 'traceback', 'types']
>>> subprocess.__all__
['Popen', 'PIPE', 'STDOUT', 'call', 'check_call', 'check_output', 'CalledProcessError']

你可以看到,大多数在 subprocess 中可见的名称实际上只是其他它导入的顶级模块。


5

为了后人,我也遇到了这个问题,并想出了一行代码解决:

import sys
parent_module = sys.modules['.'.join(__name__.split('.')[:-1]) or '__main__']

or '__main__' 部分是为了防止直接加载文件时返回自身。


这个问题回答了如何在一个模块内部获取父模块(在这里提问),但是这个问题是关于如何访问已导入的subprocess.types模块中的subprocess模块。 - undefined

0
full_module_name = module.__name__
parent, _, sub = full_module_name.rpartition('.')
if parent:
    parent = import(parent, fromlist='dummy')

这似乎无法与问题中给出的示例一起使用,无论是使用Python 3.9还是2.7:types.__name__只是'types',而不是'subprocess.types',而import(parent, fromlist='dummy')是语法错误。 - undefined

-1

我假设你还没有进入子进程模块,你可以这样做

import somemodule
children = dir(somemodule)

然后你可以使用inspect模块检查子进程的子项: http://docs.python.org/library/inspect.html 也许getmodule方法对你有用? http://docs.python.org/library/inspect.html#inspect.getmodule
import inspect
parent_module = inspect.getmodule(somefunction)
children = dir(parent_module)
package = parent_module.__package__

在我的机器上,__package__对于'types'返回为空,但对于我自己的模块来说可能更有用,因为它会将父模块作为字符串返回。

1
@orangutancloud:但他试图假装自己不知道他刚刚从subprocess导入了types--鉴于typessubprocess才是他正在寻找的答案,而不是相反。 - John Machin
@orangutancloud:inspect.getmodule(types)types.__file__ 产生的结果完全相同(在我的机器上是:'C:\\python27\\lib\\types.pyc')。这有多有用或相关呢? - John Machin
在我的机器上,它实际上返回模块对象,如果你需要函数的父级,这很有效,如果你需要父模块,我刚刚注意到__package__属性,它指向父模块作为字符串,如“somepackage.module”。 - Tom Gruner
inspect.getmodule(types) <module 'types' from '/python2.6/types.pyc'> - Tom Gruner
@orangutancloud:嗯,我错了;它确实返回实际的模块对象。如果您已经知道它是一个模块,那么这是无用的,它肯定不是指向父级的指针,也不是 module.__package__ - John Machin
显示剩余2条评论

-1
Best way worked for us was 

Let' say folder structure 

src
 |demoproject
 |
 |--> uimodule--> ui.py
 |--> backendmodule --> be.py
 setup.py
                 
1. Create installable package out of the project
2. Have __init__.py in all the directory(module)
3. create setup.py [ Keep in top level folder, here inside src]
Sample 

from setuptools import setup, find_packages

    setup(
        name="demopackage",
        version="1",
        packages=find_packages(exclude=["tests.*", "tests"]),
        author='',
        author_email='',
        description="",
        url="",
        )
        
4. From src folder, create installable package
   pip3 install .
5. this will install a package --> demopackage
6. Now from any of your module you can access any module, ex 

7. from ui.py to access be.py function calldb(), make below import

从demopackage.backendmodule.be导入calldb

8. and so on, when you a new folder into your project just add __init__.py in that folder and it will be accessible, just like above, but you have to execute `"pip3 install ."` 

抱歉,这个答案是关于如何创建Python模块的,而不是如何从任何模块访问父模块。 - jcubic
一旦您创建了一个包,就可以访问所有模块,这样更加清晰,摆脱了在PYTHONPATH或系统路径中插入路径的所有麻烦。 - sandejai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接