Imp.reload - объект NoneType не имеет атрибута 'name'

Следующий код:

def _IMPORT_(path)
    path = abspath(path)
    namespace = path[len(getcwd())+1:].replace('/', '_').strip('\\/;,. ')
    print(path)
    print(namespace)
    loader = importlib.machinery.SourceFileLoader(namespace, path+'.py')
    handle = loader.load_module(namespace)
    print(handle)
    importlib.reload(handle)
    return handle

Выдает:

/home/torxed/git/test/unitest/unix
unitest_unix
<module 'unitest_unix' from '/home/torxed/git/test/unitest/unix.py'>

Traceback (most recent call last):
  File "network.py", line 17, in <module>
    handle = sock()
  File "network.py", line 9, in __init__
    sock = _IMPORT_('./unix')
  File "/home/torxed/git/test/unitest/helpers.py", line 13, in _IMPORT_
    imp.reload(handle)
  File "/usr/lib/python3.4/imp.py", line 315, in reload
    return importlib.reload(module)
  File "/usr/lib/python3.4/importlib/__init__.py", line 149, in reload
    methods.exec(module)
  File "<frozen importlib._bootstrap>", line 1134, in exec
AttributeError: 'NoneType' object has no attribute 'name'

Это прекрасно работает в Python 3.3.5, где была введена такая операция (раньше была такая же импортная механика). Однако на Python 3.4.2 Это, по-видимому, не работает.

Что изменилось с 3.3.5? Невозможно найти никаких следов или изменение находится где-то посередине релизов. В прошлом году был исправлен патч для этого точного поведения, когда переменные окружения не были переданы, но, похоже, здесь работает.

Ответ 1

Я получаю ту же ошибку, когда пытаюсь перезагрузить файл после переключения папок.

Например:


Создайте простой модуль:

In [10]: %%file temp.py
    ...: message = "Hello World!"
    ...: 
Writing temp.py

Загрузите модуль и распечатайте сообщение:

In [14]: import temp
    ...: print(temp.message)
Hello World!

Измените сообщение:

In [17]: temp.message = 'Hello brave new world!'
    ...: print(temp.message)
Hello brave new world!

Перезагрузите модуль, чтобы вернуть исходное сообщение:

In [18]: import imp
    ...: imp.reload(temp)
    ...: print(temp.message)
Hello World!

Все хорошо до сих пор...


Теперь измените пути:

In [20]: cd ..

Попробуйте перезагрузить модуль:

In [24]: imp.reload(temp)
Traceback (most recent call last):

  File "<ipython-input-24-7fa95de0f250>", line 1, in <module>
imp.reload(temp)

  File "/home/user/anaconda3/lib/python3.4/imp.py", line 315, in reload
return importlib.reload(module)

  File "/home/user/anaconda3/lib/python3.4/importlib/__init__.py", line 149, in reload
methods.exec(module)

  File "<frozen importlib._bootstrap>", line 1134, in exec

AttributeError: 'NoneType' object has no attribute 'name'

В моем случае решение заключалось в том, чтобы вернуться к пути, в котором импорт был сделан изначально.

Ответ 2

Действительно, importlib.reload работает только в том случае, если вы находитесь в правильном каталоге. Чтобы обойти это, я написал вспомогательную функцию, которую я могу вызвать:

def reload( module ):
  import os
  import os.path
  import importlib

  cwd = os.getcwd()
  os.chdir( os.path.dirname(os.path.abspath(module.__file__)) )
  importlib.reload( module )
  os.chdir( cwd )