1

I'm trying to write a Python program that registers multiple importable modules while still being a single file.

I have a simple python program called import_module ... it's intended to define a module called foo whose implementation resides in a string literal.

In the example below, compile is called before foo is imported, but the compiled code object is simply discarded. What do I need to do in order to associate it to the name foo so that import foo will work?

#! /usr/bin/env python

compile(
'''
def hello():
    print("hello")
''',
'foo',
'exec'
)

import foo
foo.hello()

When run, this program produces the error:

./import_module 
Traceback (most recent call last):
  File "./import_module", line 12, in <module>
    import foo
ImportError: No module named foo
Exit 1

I'd like it to print hello, but am not sure what to do with the code object to register it with the import system.

Ideally, I'd like to do this in such a way that it works independently of version. I'm trying to write a single script that can be run on systems where python is either python2 or 3+.

If no such version independent-method of registering modules exists, I'm okay with inspecting the version info and doing something different depending on the version.

Greg Nisbet
  • 6,710
  • 3
  • 25
  • 65
  • Good question, but this may depend on the Python version you're using. Could you specify the version, perhaps by adding the appropriate tag? (Or if you want an answer that covers all versions in common use, it would be useful to say that explicitly.) – David Z Aug 31 '18 at 03:00
  • 1
    Are you looking for `exec`? You probably want to pass the compiled code object to `exec`, or just directly `exec` the string. – juanpa.arrivillaga Aug 31 '18 at 03:05
  • @juanpa.arrivillaga I don't think `exec` exposes the functionality I want. I'm looking to write something kind of like `waf` where there's a specially named executable that sets up a Python environment with a bunch of libraries and then transfers control to a user-provided script. The waf executable is also a self-contained file, but it's implemented as a self-extracting archive (I think). – Greg Nisbet Aug 31 '18 at 03:11
  • Do you mean you want use it like `executable user-script.py`, and then it can setup a bunch of libraries? I think you can read `user-script.py` and `exec` it in your `executable`. – Sraw Aug 31 '18 at 03:17
  • https://stackoverflow.com/q/5362771/2988730 – Mad Physicist Aug 31 '18 at 03:21
  • @Sraw yes, but then functions that I implement in `executable` that are meant to be internal would be visible to the user script. And have the API exposed by `executable` be separated out into modules. – Greg Nisbet Aug 31 '18 at 03:22
  • 2
    Create an empty module, run your code in its namespace, add it to sys.modules. No need for the import statement. – Mad Physicist Aug 31 '18 at 03:23
  • @GregoryNisbet I am unfamiliar with `waf`. But if your goal is to hide internals, I would say spare the effort in Python. Or if you really want an executable that can obscure internals, use a C-extension, or better yet, Cython. You can automate all that using `subprocess` at the interpreter level. – juanpa.arrivillaga Aug 31 '18 at 03:42

0 Answers0