python-分配给sys.modules时检查模块名称是否有效

时间:2018-09-01 00:15:21

标签: python

sys.modules中设置项目时,一些令人惊讶的值将用作键:

$ python
>>> import sys
>>> sys.modules["27"] = 123
>>> sys.modules["27"]
123
>>> sys.modules[True] = 123
>>> sys.modules[(1, 7)] = 123

实际上,typesys.modules标识为标准词典...我发现这真的很令人惊讶。

Python2

>>> type(sys.modules)
<type 'dict'>

Python3(在类型/类统一之后)

>>> type(sys.modules)
<class 'dict'>

但是,使用普通的import机制现在完全无法访问那些“模块”。

Python标准库中是否有一个函数可用于识别“良好”模块名称/点分隔模块“路径”。我想挑选出可以使用import语法导入的内容,并且通常遵循该语言的约定。理想情况下,我希望它是标准库(如果存在)的一部分,以便它可以跟踪对Python本身的更改。

1 个答案:

答案 0 :(得分:2)

从技术上讲 sys.modules中的某些东西“可导入”所需的全部是字符串,据我所知

>>> sys.modules['where is your god now?'] = 42
>>> __import__('where is your god now?')
42

此限制是由内置的__import__施加的:

>>> __import__(42)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __import__() argument 1 must be str, not int

甚至是unicode!

>>> sys.modules['☃'] = 'looking like christmas?'
>>> __import__('☃')
'looking like christmas?'

尽管要使用import 语句,但您需要将事物作为标识符:

>>> sys.modules['josé'] = ':wave:'
>>> import josé
>>> josé
':wave:'

在python3中,您可以使用isidentifier方法对字符串进行检查(如果是python2,它遵循[a-zA-Z_][a-zA-Z0-9_]*,我相信这是标识符):

>>> 'foo'.isidentifier()
True
>>> 'josé'.isidentifier()
True
>>> '☃'.isidentifier()
False
>>> 'hello world'.isidentifier()
False

如果要处理点名:

def dotted_name_is_identifier(x):
    return all(s and s.isidentifier() for s in x.split('.'))

用法:

>>> dotted_name_is_identifier('foo.bar')
True
>>> dotted_name_is_identifier('hello.josé')
True
>>> dotted_name_is_identifier('hello. world')
False
>>> dotted_name_is_identifier('hello..world')
False
>>> dotted_name_is_identifier('hello.world.')
False