问题
I have a long list of possible files I need to import. I will only ever need 1 of them and they all have the same interface. (Choosing a payment gateway to process a payment)
Suppose I have a dictionary that represents the name of all the gateway files.
i.e.
gateways = {
'1' : 'authorize',
'2' : 'paysimple',
'3' : 'braintreepayments',
'4' : 'etc',
}
I know the keys to this dictionary based on information from a database. So, if I receive a payment process request with a gateway value of 1 I know it needs to be handled by Authorize.net. A 2 is to be processed by Pay Simple. Etc.
I'd like to be able to create an import statement that is built with the information I know rather than a horrible list of elif
statements.
Consider the simple method below:
# For the purposes of this example assume payment_gateway is defined
# elsewhere and represents the key to the dictionary
gateway_file = gateways.get(payment_gateway)
import_str = "from gateway_interface.%s import process" % gateway_file
gogo(import_str)
Where gogo
is a way to cause the import statement to actually import.
Is such a thing possible?
回答1:
Simplest
process = __import__('gateway_interface.'+gateway_file,fromlist=['foo']).process
EDIT: 'foo' in the fromlist can be anything, as long as fromlist is not an emptylist. That little bit of strangeness is explained in Why does Python's __import__ require fromlist?.
I also had to edit because in my first post __import__
didn't work as expected as further described in Python's __import__ doesn't work as expected.
if you have python 2.7
import importlib
process = importlib.import_module('gateway_interface.'+gateway_file).process
WAAAAY cool would be to use package_tools (e.g. from pkg_resources import iter_entry_points
)
That could give you a solution to find the right function even if they are in odd packages not under gateway_interface. If they are all on one place and you don't need the sytle-point that is overkill so ... yeah just __import__
回答2:
Take a look at the imp module which allows you to access the internals of the import statement, or the __import__ method itself - either of these should allow you to achieve what you describe I think.
回答3:
The builtin __import__
method should work:
process = __import__(gateways.get(payment_gateway)).process
来源:https://stackoverflow.com/questions/11404617/create-an-import-statement-using-variable-interpolation