Import file using string as name [duplicate]

2019-01-23 07:14发布

问题:

Possible Duplicate:
Dynamic module import in Python

I intend to make a suite of files at some point soon, and the best way to organize it is to have a list, that list will be at the very top of a file, and after it will come a ridiculous amount of code to handle what that list controls and how it operates. I'm looking to write said list only once, and said list is a list of folder and file names in this format:

[(folder/filename, bool, bool, int), (folder/filename, bool, bool, int)]

As you can see, folder/filename are the same (sort of). File name is folder name with .py on the end, but doing import XXX you don't need to do import XXX.py, so I don't see this causing an issue.

The problem I'm facing is importing using this method...

for (testName, auto, hardware, bit) in testList:
    print(testName)
    paths = "\\" + testName
    print paths
    addpath(paths)
    sys.modules[testName] = testName # One of a few options I've seen suggested on the net
    print("Path Added")
    test = testName + ".Helloworld()"
    eval(test)

So for each test I have, print the name, assemble a string which contains the path ("\\testName"), for this example, print the test path, then add the path to the list (sys.path.append(path)), then print to confirm it happened, then assemble a string which will be executed by eval for the tests main module and eventually eval it.

As you can see, I'm currently having to have a list of imports at the top. I can't simply do import testName (the contents of testName are the name of the module I wish to import), as it will try to find a module called testName, not a module called the contents of testName.

I've seen a few examples of where this has been done, but can't find any which work in my circumstances. If someone could literally throw a chunk of code which does it that would be wonderful.

I'd also request that I'm not hung, drawn, nor quartered for use of eval, it is used in a very controlled environment (the list through which it cycles is within the .py file, so no "end user" should mess with it).

回答1:

Not sure if I understood everything correctly, but you can import a module dynamically using __import__:

mod = __import__(testName)
mod.HelloWorld()

Edit: I wasn't aware that the use of __import__ was discouraged by the python docs for user code: __import__ documentation (as noted by Bakuriu)

This should also work and would be considered better style:

import importlib

mod = importlib.import_module(testName)
mod.HelloWorld()


回答2:

  1. Never, ever, ever mess with sys.modules directly if you don't know exactly what you are doing.
  2. There are a lot of ways to do what you want:
    1. The build-in __import__ function
    2. Using imp.load_module
    3. Using importlib.import_module

I'd avoid using __import__ directly, and go for importlib.import_module(which is also suggested at the end of the documentation of __import__).



回答3:

Add the path where module resides to sys.path. Import the module using __import__ function which accepts a string variable as module name.

import sys
sys.path.insert(0, mypath)  # mypath = path of module to be imported
imported_module = __import__("string_module_name") # __import__ accepts string 
imported_module.myfunction()   # All symbols in mymodule are now available normally