javascript - In python, "export" a custom-tailored object from a module - Stack Overflow

In JavaScript, specifically in node.js setting, one can spell module.exports = 13; in module.js, then x

In JavaScript, specifically in node.js setting, one can spell module.exports = 13; in module.js, then x = import ("module.js"); elsewhere and have 13 assigned to x directly.

This saves some code when a module exports a single function, and I notice a lot of widely used packages (such as through2) make use of it.

Is there a way to do the same in Python? With some black magic, maybe?

I do have heard of a thing called loader that's, I guess, supposed to do some manipulations with a module before making it available. In particular, I think SaltStack makes use of something like that in salt.loader, but the code is too hard for me to follow. I imagine we could write a function similar to this:

def loader(module):
    m = __import__(module)
    return m["__exports__"]

— Then define __exports__ somewhere in a module we want to import and enjoy functionality very similar to JavaScript's module.exports mechanics. But unfortunately TypeError: 'module' object has no attribute '__getitem__' prevents us from doing that.

In JavaScript, specifically in node.js setting, one can spell module.exports = 13; in module.js, then x = import ("module.js"); elsewhere and have 13 assigned to x directly.

This saves some code when a module exports a single function, and I notice a lot of widely used packages (such as through2) make use of it.

Is there a way to do the same in Python? With some black magic, maybe?

I do have heard of a thing called loader that's, I guess, supposed to do some manipulations with a module before making it available. In particular, I think SaltStack makes use of something like that in salt.loader, but the code is too hard for me to follow. I imagine we could write a function similar to this:

def loader(module):
    m = __import__(module)
    return m["__exports__"]

— Then define __exports__ somewhere in a module we want to import and enjoy functionality very similar to JavaScript's module.exports mechanics. But unfortunately TypeError: 'module' object has no attribute '__getitem__' prevents us from doing that.

Share Improve this question edited May 14, 2017 at 14:00 gz. 6,7011 gold badge24 silver badges34 bronze badges asked May 14, 2017 at 13:15 Ignat InsarovIgnat Insarov 4,84221 silver badges38 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 2

Python has importing built in to the language at a more basic level than Javascript does, almost all use cases are covered by a simple import statement.

For your example, all it really boils down to is:

from module import exports as x

So, there's not need to look for code savings by changing module.

The other part of the question is how, as a module author, would you restrict people to seeing only a single symbol.

Generally this is not required except to help users know what are public functions vs implementation details. Python has a few mon idioms for this:

  • Any names that start with a leading underscore, such as _helper, are considered private. They can be accessed as normal, but the implication is you should not.
  • If a module level variable __all__ = [...] exists, only the strings it contains are considered public. The names must seperatedly be declared in the module.

As well as being documentation, both of these do affect one aspect of the module import:

from module import *

Using a star import is generally discouraged, but only public names will be brought in to the local namespace.

After some thinking I understood that, while we can't say m["__exports__"] due to module object's class not having __getitem__ method, we can still access some of the module's elements with "dot" notation: m.__exports__ works.

Another way: screen all module level names off with an underscore and assign the object to be exported to a variable named after the module, then from module import *.

loader.py:

def loader(module):
    m = __import__(module)
    return m.__exports__

exports.py:

def _f():
    return 13

_a = 31

exports = {"p6": _f, "p8": _a}

__exports__ = exports

Python 2.7:

>>> import loader
>>> e = loader.load ("exports")
>>> e
{'p8': 31, 'p6': <function _f at 0x7fb79d494cf8>}
>>> from exports import *
>>> exports
{'p8': 31, 'p6': <function _f at 0x7fb79d494cf8>}

Python 3:

>>> import loader
>>> e = loader.load ("exports")
>>> e
{'p6': <function _f at 0x7f88ae229ae8>, 'p8': 31}
>>> from exports import *
>>> exports
{'p6': <function _f at 0x7f88ae229ae8>, 'p8': 31}

In the first way proposed, I unfortunately cannot use __all__ in loader.load to filter only listed names from a module being loaded since __getitem__ is not defined for module object.

In the second way proposed I don't get so much control (in that a malicious module can export arbitrary names and manipulate my namespace) and flexibility (in that I cannot assign the module's exported object to arbitrary name anywhere in my code).

So, there is still a bit left to be desired here.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745503918a4630541.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信