python - проверить правильность имени модуля при назначении sys.modules

1

Когда элементы настроек внутри sys.modules, некоторые удивительные значения будут использоваться в качестве ключей:

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

Фактически, type идентифицирует sys.modules как стандартный словарь... который я нашел действительно удивительным.

python2

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

Python3 (после объединения типов/классов)

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

Однако эти "модули" теперь полностью недоступны с использованием обычного механизма import.

Есть ли функция в стандартной библиотеке Python, которая может быть использована для распознавания "хороших" имен модулей/"разделов" между отдельными модулями. Я хочу выбрать элементы, импортируемые с использованием синтаксиса import и, как правило, следуют соглашениям языка. В идеале мне бы хотелось, чтобы часть стандартной библиотеки (если она существует) так, чтобы она отслеживала изменения самого Python.

Теги:

1 ответ

2
Лучший ответ

технически все, что нужно для чего-то в sys.modules быть "импортируемым", должно быть строкой, насколько я могу судить

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

Ограничение накладывается __import__ builtin:

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

Даже юникод!

>>> 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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню