Почему. модуль импорта не работает, когда __name__ == & ldquo; __ main __ & rdquo; в Python [дубликат]

Если вы видите эту ошибку после перемещения java-файлов или каталогов в другие местоположения, вы можете гарантировать, что Android Studio запуталась. И угадай что? отмена этих действий не устраняет проблему.

Итак, вы пытаетесь очистить, но это не работает.

И перезапуск тоже не работает.

Но попробуйте File -> Invalidate Caches / Restart ... -> Invalidate and Restart

Android Studio поддерживает информацию о том, какие файлы зависят от других файлов. И поскольку перемещение файлов вокруг не выполняется правильно, перемещение файлов вызывает ошибки. И это еще не все: кеши этих зависимостей используются в попытке ускорить сборку.

Это означает, что вы не только должны перезагружаться, но вам необходимо аннулировать эти кэши для восстановления (или, точнее, перестроить) здравомыслие.

449
задан martineau 4 May 2017 в 16:13
поделиться

8 ответов

, к сожалению, этот модуль должен находиться внутри пакета, и иногда он должен исполняться как скрипт. Любая идея, как я мог бы это достичь?

Это довольно распространенный способ иметь такой макет ...

main.py
mypackage/
    __init__.py
    mymodule.py
    myothermodule.py

... с mymodule.py как это ...

#!/usr/bin/env python3

# Exported function
def as_int(a):
    return int(a)

# Test function for module  
def _test():
    assert as_int('1') == 1

if __name__ == '__main__':
    _test()

... a myothermodule.py как это ...

#!/usr/bin/env python3

from .mymodule import as_int

# Exported function
def add(a, b):
    return as_int(a) + as_int(b)

# Test function for module  
def _test():
    assert add('1', '1') == 2

if __name__ == '__main__':
    _test()

... и a main.py как это ...

#!/usr/bin/env python3

from mypackage.myothermodule import add

def main():
    print(add('1', '1'))

if __name__ == '__main__':
    main()

... который отлично работает при запуске main.py или mypackage/mymodule.py, но с ошибкой mypackage/myothermodule.py из-за относительного импорта ...

from .mymodule import as_int

Способ, которым вы должны запускать его, - это ...

python3 -m mypackage.myothermodule

... но он несколько подробный и не очень хорошо сочетается с строкой shebang, например #!/usr/bin/env python3.

Самое простое исправление для этого случая, если имя mymodule уникально глобально, было бы избежать использования относительного импорта и просто использовать ...

from mymodule import as_int

... хотя, если это не уникально или ваша структура пакета более сложна, вам нужно будет включить каталог, содержащий каталог вашего пакета в PYTHONPATH, и сделать это так:

from mypackage.mymodule import as_int

.. . Если вы хотите, чтобы он работал «из коробки», вы можете frob PYTHONPATH в коде сначала с этим ...

import sys
import os

PACKAGE_PARENT = '..'
SCRIPT_DIR = os.path.dirname(os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__))))
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))

from mypackage.mymodule import as_int

Это какая-то боль, но есть clu e о том, почему в электронное письмо написано неким Гвидо ван Россумом ...

Я на этом и на любых других предложенных твидлингах __main__. Единственный случай использования, похоже, заключается в запуске скриптов, которые, случается, живут внутри каталога модуля, который я всегда рассматривал как антипаттерн. Чтобы заставить меня передумать, вы должны были бы убедить меня, что это не так.

Не работает ли скрипт внутри пакета антипаттерн или нет, но лично я нахожу его действительно полезно в пакете, который содержит некоторые пользовательские виджеты wxPython, поэтому я могу запустить скрипт для любого из исходных файлов, чтобы отобразить wx.Frame, содержащий только этот виджет для тестирования.

339
ответ дан Aya 18 August 2018 в 00:01
поделиться
  • 1
    Лучший способ получить SCRIPTDIR приведен в комментарий Импортировать модуль из относительного пути в качестве os.path.realpath(os.path.dirname(inspect.getfile(inspect.currentframe()))), если вы уверены, что ваш модуль всегда имеет правильное значение file, вы также можете использовать os.path.realpath(os.path.dirname(__file__)) , – marcz 12 March 2014 в 16:31
  • 2
    +1 ...so I can run the script for any of the source files ...for testing purposes. Это именно тот случай, который привел меня к этому вопросу – tel 14 October 2016 в 19:53
  • 3
    Вы можете расширить свой PYTHONPATH, применив более короткий и читаемый фрагмент кода: sys.path.append( os.path.join( os.path.dirname(__file__), os.path.pardir ) ) – Alex-Bogdanov 2 December 2016 в 16:19
  • 4
    У меня все еще были проблемы при работе со сценарием, имеющим то же имя, что и пакет, например. в foo/foo.py: from foo.bar import baz. Вставка пути в начале, а не добавление, решила проблему. Полная команда: sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.path.pardir)) – Agargara 18 October 2017 в 04:37

Поместите это в файл __init__.py вашего пакета:

# For relative imports to work in Python 3.6
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))

Предполагая, что ваш пакет выглядит следующим образом:

├── project
│   ├── package
│   │   ├── __init__.py
│   │   ├── module1.py
│   │   └── module2.py
│   └── setup.py

Теперь используйте регулярный импорт в вашем пакете, например:

# in module2.py
from module1 import class1

Это работает как в python 2, так и в 3.

10
ответ дан Brian Burns 18 August 2018 в 00:01
поделиться

Чтобы устранить эту проблему, я разработал решение с пакетом repackage , который работал для меня в течение некоторого времени. Он добавляет верхний каталог в путь lib:

import repackage
repackage.up()
from mypackage.mymodule import myfunction

Repackage может сделать относительный импорт, который работает в широком диапазоне случаев, используя интеллектуальную стратегию (проверка стека вызовов).

1
ответ дан fralau 18 August 2018 в 00:01
поделиться

Надеюсь, это будет полезно для кого-то там - я прошел через полдюжины записей stackoverflow, пытаясь выяснить относительный импорт, похожий на то, что было опубликовано здесь. Я настроил все, как было предложено, но я все еще нажимал ModuleNotFoundError: No module named 'my_module_name'

. Поскольку я только развивался локально и играл, я не создал / не запустил файл setup.py. Я также, по-видимому, не установил свой PYTHONPATH.

Я понял, что когда я запускал свой код так, как я был, когда тесты были в том же каталоге, что и модуль, я не смог найти свой модуль:

$ python3 test/my_module/module_test.py                                                                                                               2.4.0
Traceback (most recent call last):
  File "test/my_module/module_test.py", line 6, in <module>
    from my_module.module import *
ModuleNotFoundError: No module named 'my_module'

, когда я явно указал, что путь начал работать:

$ PYTHONPATH=. python3 test/my_module/module_test.py                                                                                                  2.4.0
...........
----------------------------------------------------------------------
Ran 11 tests in 0.001s

OK

Итак, в случае, если кто-то попробовал несколько предложений, считает, что их код структурирован правильно и все еще находится в аналогичной ситуации я попробую выполнить одно из следующих действий, если вы не экспортируете текущий каталог в свой PYTHONPATH:

  1. Запустите свой код и явно включите путь следующим образом: $ PYTHONPATH=. python3 test/my_module/module_test.py
  2. Чтобы избежать вызова PYTHONPATH=., создайте файл setup.py с содержимым следующего типа и запустите python setup.py development, чтобы добавить пакеты в путь:
# setup.py
from setuptools import setup, find_packages

setup(
    name='sample',
    packages=find_packages()
)
1
ответ дан LaCroixed 18 August 2018 в 00:01
поделиться

Я столкнулся с этой проблемой. Обходной путь взлома импортируется через блок if / else, например:

#!/usr/bin/env python3
#myothermodule

if __name__ == '__main__':
    from mymodule import as_int
else:
    from .mymodule import as_int


# Exported function
def add(a, b):
    return as_int(a) + as_int(b)

# Test function for module  
def _test():
    assert add('1', '1') == 2

if __name__ == '__main__':
    _test()
28
ответ дан Leon 18 August 2018 в 00:01
поделиться
  • 1
    это не очень хорошее решение. тоже, голый except: плохой. используйте except ImportError: вместо этого! – ThiefMaster♦ 16 March 2015 в 20:07
  • 2
    Здесь SystemError. (Py 3.4) – Avi 1 November 2015 в 19:31
  • 3
    Это не страшная идея, но было бы лучше определить, какой импорт использовать, а не пытаться / исключать. Что-то вроде if __name__ == '__main__': from mymod import as_int; else: from .mymod import as_int. – Perkins 22 February 2016 в 05:08
  • 4
    @Perkins Ну ... в большинстве случаев это не . Я думаю, что относительный импорт может быть исключением. – wizzwizz4 13 June 2018 в 17:26

, если оба пакета находятся в вашем пути импорта (sys.path), а модуль / класс, который вы хотите, находится в примере / example.py, затем для доступа к классу без относительного импорта выполните:

from example.example import fkt
1
ответ дан Salt999 18 August 2018 в 00:01
поделиться
155
ответ дан vaultah 18 August 2018 в 00:01
поделиться
0
ответ дан Árthur 29 October 2018 в 22:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: