13

I need to know if there is a way to access parent modules from submodules. If I import submodule:

from subprocess import types

I have types - is there some Python magic to get access to subprocess module from types? Something similar to this for classes ().__class__.__bases__[0].__subclasses__().

jcubic
  • 61,973
  • 54
  • 229
  • 402
  • 5
    Your example is weird -- `types` is actually the standard Python `types` module. Your import line will do the same as `import types`, and `types` will be exactly the same module object in both cases. – Sven Marnach Mar 12 '11 at 23:16
  • 1
    subprocess is not the "parent" of the `types` module in any sense that appears meaningful or useful to me. `subprocess` has evidently imported `types`, just like many other modules import `types`. What are you trying to do? What are you trying to do? – John Machin Mar 13 '11 at 00:40
  • 1
    I know that types is standard module, but I found it in subprocess modules when I search for all submodules. – jcubic Mar 14 '11 at 01:48
  • @John I try to block access to filesystem and the shell. – jcubic Mar 14 '11 at 01:49
  • @jcubic If you've still got this project in production, please stop users having access to it. I'll break out of the sandbox you've made if it'll convince you. I can break out of a sandbox with no builtins whatsoever, where only literals are allowed. – wizzwizz4 Jun 13 '18 at 18:25
  • 1
    @wizzwizz4 it was years ago that I learn this hard way, someone wipe out disk on my shared hosting. It was for my https://trypython.jcubic.pl/ I've needed to disable it but few years later I've found brython in js and now It use this library. – jcubic Jun 13 '18 at 18:57

5 Answers5

7

If you've accessed a module you can typically get to it from the sys.modules dictionary. Python doesn't keep "parent pointers" with names, particularly because the relationship is not one-to-one. For example, using your example:

>>> 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'>

If you'll note the presence of types in the subprocess module is just an artifact of the import types statement in it. You just import types if you need that module.

In fact, a future version of subprocess may not import types any more, and your code will break. You should only import the names that appear in the __all__ list of a module; consider other names as implementation details.

So, for example:

>>> 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']

You can see that most of the names visible in subprocess are just other top-level modules that it imports.

Nicholas Riley
  • 43,532
  • 6
  • 101
  • 124
5

For posterity, I ran into this also and came up with the one liner:

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

The or '__main__' part is just in case you load the file directly it will return itself.

Dorian B.
  • 1,101
  • 13
  • 22
0
full_module_name = module.__name__
parent, _, sub = full_module_name.rpartition('.')
if parent:
    parent = import(parent, fromlist='dummy')
Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69
kai
  • 1,640
  • 18
  • 11
-1

I assume you are not inside the subprocess module already, you could do

import somemodule
children = dir(somemodule)

Then you could inspect the children of subprocess with the inspect module: http://docs.python.org/library/inspect.html

Maybe the getmodule method would be useful for you? http://docs.python.org/library/inspect.html#inspect.getmodule

import inspect
parent_module = inspect.getmodule(somefunction)
children = dir(parent_module)
package = parent_module.__package__

On my machine __package__ returns empty for 'types', but can be more useful for my own modules as it does return the parent module as a string

Tom Gruner
  • 9,635
  • 1
  • 20
  • 26
  • 1
    @orangutancloud: But he's trying to pretend that he doesn't know that he just imported `types` from `subprocess` -- Given `types`, `subprocess` is the ANSWER that he's seeking, not the other way around. – John Machin Mar 12 '11 at 23:24
  • @john good point, I tried to edit the answer to be more helpful. The inspect module in python is one of my favorite parts about the language. – Tom Gruner Mar 12 '11 at 23:33
  • @orangutancloud: `inspect.getmodule(types)` produces exactly the same as `types.__file__` (on my machine: `'C:\\python27\\lib\\types.pyc'`). How helpful or relevant is that? – John Machin Mar 12 '11 at 23:50
  • On my machine it does actually return the module object, if you need the parent of a function this works well, if you need the parent module I just noticed the __package__ property which points to the parent module as a string like 'somepackage.module' – Tom Gruner Mar 13 '11 at 00:02
  • inspect.getmodule(types) – Tom Gruner Mar 13 '11 at 00:04
  • @orangutancloud: Ermmm, I was wrong; it does return the actual module object. This is useless if you know already that it's a module, and it certainly is not a pointer to the parent as the OP defines it, and neither is `module.__package__`. – John Machin Mar 13 '11 at 00:38
  • Yeah, it's not really that useful. This one is a bit tricky without a more specific use case, since types and subprocess are just examples. I think I am going to give up on this one. – Tom Gruner Mar 13 '11 at 00:42
-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

from demopackage.backendmodule.be import 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 ."` 
sandejai
  • 931
  • 1
  • 15
  • 22
  • Sorry, this answer how to create a Python module not how to access the parent module from any module. – jcubic Oct 14 '22 at 15:19
  • You can access the all module once you create a package, it's much cleaner, free from all those hacks of inserting paths in PYTHONPATH or system path.. – sandejai Oct 15 '22 at 16:30