Ошибка импорта питон

I have a specific problem which might require a general solution. I am currently learning apache thrift. I used this guide.I followed all the steps and i am getting a import error as Cannot import module UserManager. So the question being
How does python import lookup take place. Which directory is checked first. How does it move upwards?
How does sys.path.append(») work?

I found out the answer for this here. I followed the same steps. But i am still facing the same issue. Any ideas why? Anything more i should put up that could help debug you guys. ?

Help is appreciated.

asked May 26, 2015 at 10:34

Saras Arya's user avatar

Saras AryaSaras Arya

2,9828 gold badges39 silver badges71 bronze badges

0

On windows, Python looks up modules from the Lib folder in the default python path, for example from «C:Python34Lib». You can add your Python libaries in a custom folder («my-lib» or sth.) in there, but you need a file in order to tell Python that you can import from there. This file is called __init__.py , and is totally empty. That data structure should look like this:

my-lib

  • __init__.py
  • /myfolder
  • mymodule.py

    (This is how every Python module works. For example urllib.request, it’s at «%PYTHONPATH%Liburllibrequest.py»)

    You can import from the «mymodule.py» file by typing

    import my-lib
    

    and then using

    mylib.mymodule.myfunction
    

    or you can use

    from my-lib import mymodule
    

    And then just using the name of you function.

    You can now use sys.path.append to append the path you pass into the function to the folders Python looks for the modules (Please note that thats not permanent). If the path of your modules should be static, you should consider putting these in the Lib folder. If that path is relative to your file you could look for the path of the file you execute from, and then append the sys.path relative to your file, but i reccomend using relative imports.

    If you consider doing that, i recommend reading the docs, you can do that here: https://docs.python.org/3/reference/import.html#submodules

  • answered May 26, 2015 at 15:28

    Agilix's user avatar

    AgilixAgilix

    3141 silver badge13 bronze badges

    2

    If I got you right, you’re using Python 3.3 from Blender but try to include the 3.2 standard library. This is bound to give you a flurry of issues, you should not do that. Find another way. It’s likely that Blender offers a way to use the 3.3 standard library (and that’s 99% compatible with 3.2). Pure-Python third party library can, of course, be included by fiddling with sys.path.

    The specific issue you’re seeing now is likely caused by the version difference. As people have pointed out in the comments, Python 3.3 doesn’t find the _tkinter extension module. Although it is present (as it works from Python 3.2), it is most likely in a .so file with an ABI tag that is incompatible with Blender’s Python 3.3, hence it won’t even look at it (much like a module.txt is not considered for import module). This is a good thing. Extension modules are highly version-specific, slight ABI mismatches (such as between 3.2 and 3.3, or two 3.3 compiled with different options) can cause pretty much any kind of error, from crashes to memory leaks to silent data corruption or even something completely different.

    You can verify whether this is the case via import _tkinter; print(_tkinter.file) in the 3.2 shell. Alternatively, _tkinter may live in a different directory entirely. Adding that directory won’t actually fix the real issue outlined above.

    answered May 26, 2015 at 10:40

    Ravinther M's user avatar

    Ravinther MRavinther M

    2632 silver badges13 bronze badges

    For any new readers coming along that are still having issues, try the following. This is cleaner than using sys.path.append if your app directory is structured with your .py files that contain functions for import underneath your script that imports those files. Let me illustrate.

    Script that imports files: main.py

    Function files named like: func1.py

    main.py
       /functionfolder
          __init__.py
          func1.py
          func2.py
    

    The import code in your main.py file should look as follows:

    from functionfolder import func1
    from functionfolder import func2
    

    As Agilix correctly stated, you must have an __init__.py file in your «functionfolder» (see directory illustration above).

    In addition, this solved my issue with Pylance not resolving the import, and showing me a nagging error constantly. After a rabbit-hole of sifting through GitHub issues, and trying too many comparatively complicated proposed solutions, this ever-so-simple solution worked for me.

    answered Apr 13, 2021 at 1:34

    Sean Richards's user avatar

    You may try with declaring sys.path.append(‘/path/to/lib/python’) before including any IMPORT statements.

    answered May 26, 2015 at 10:40

    Pralhad Narsinh Sonar's user avatar

    I just created a __init__.py file inside my new folder, so the directory is initialised, and it worked (:

    answered Feb 1, 2022 at 13:10

    Luis's user avatar

    1

    Jan 5, 2018 10:00:56 AM |
    Python Exception Handling: ImportError and ModuleNotFoundError

    A look into the ImportError and ModuleNotFoundError in Python, with code showing how to deal with failed imports in Python 2.7 and 3.6.

    Making our way through our detailed Python Exception Handling series we arrive at the ImportError, along with its single child subclass of ModuleNotFoundError. The ImportError is raised when an import statement has trouble successfully importing the specified module. Typically, such a problem is due to an invalid or incorrect path, which will raise a ModuleNotFoundError in Python 3.6 and newer versions.

    Within this article we’ll explore the ImportError and ModuleNotFoundError in a bit more detail, beginning with where they sit in the overall Python Exception Class Hierarchy. We’ll also take a look at some simple code samples that illustrate the differences in import statement failures across newer (3.6) and older (2.7) versions of Python, so let’s get started!

    The Technical Rundown

    All Python exceptions inherit from the BaseException class, or extend from an inherited class therein. The full exception hierarchy of this error is:

    • BaseException
      • Exception
        • ImportError
          • ModuleNotFoundError

    Full Code Sample

    Below is the full code sample we’ll be using in this article. It can be copied and pasted if you’d like to play with the code yourself and see how everything works.

    # outer_import_2.7.py
    import sys
    import gw_utility.Book

    def main():
    try:
    print(sys.version)
    except ImportError as error:
    # Output expected ImportErrors.
    print(error.__class__.__name__ + ": " + error.message)
    except Exception as exception:
    # Output unexpected Exceptions.
    print(exception, False)
    print(exception.__class__.__name__ + ": " + exception.message)

    if __name__ == "__main__":
    main()

    # inner_import_2.7.py
    import sys

    def main():
    try:
    print(sys.version)
    import gw_utility.Book
    except ImportError as error:
    # Output expected ImportErrors.
    print(error.__class__.__name__ + ": " + error.message)
    except Exception as exception:
    # Output unexpected Exceptions.
    print(exception, False)
    print(exception.__class__.__name__ + ": " + exception.message)

    if __name__ == "__main__":
    main()

    # outer_import_3.6.py
    import sys
    import gw_utility.Book
    from gw_utility.logging import Logging

    def main():
    try:
    Logging.log(sys.version)
    except ImportError as error:
    # Output expected ImportErrors.
    Logging.log_exception(error)
    # Include the name and path attributes in output.
    Logging.log(f'error.name: {error.name}')
    Logging.log(f'error.path: {error.path}')
    except Exception as exception:
    # Output unexpected Exceptions.
    Logging.log_exception(exception, False)

    if __name__ == "__main__":
    main()

    # inner_import_3.6.py
    import sys
    from gw_utility.logging import Logging

    def main():
    try:
    Logging.log(sys.version)
    import gw_utility.Book
    except ImportError as error:
    # Output expected ImportErrors.
    Logging.log_exception(error)
    # Include the name and path attributes in output.
    Logging.log(f'error.name: {error.name}')
    Logging.log(f'error.path: {error.path}')
    except Exception as exception:
    # Output unexpected Exceptions.
    Logging.log_exception(exception, False)

    if __name__ == "__main__":
    main()

    # logging.py
    import math
    import sys
    import traceback

    class Logging:
    separator_character_default = '-'
    separator_length_default = 40

    @classmethod
    def __output(cls, *args, sep: str = ' ', end: str = 'n', file=None):
    """Prints the passed value(s) to the console.

    :param args: Values to output.
    :param sep: String inserted between values, default a space.
    :param end: String appended after the last value, default a newline.
    :param file: A file-like object (stream); defaults to the current sys.stdout.
    :return: None
    """
    print(*args, sep=sep, end=end, file=file)

    @classmethod
    def line_separator(cls, value: str = None, length: int = separator_length_default,
    char: str = separator_character_default):
    """Print a line separator with inserted text centered in the middle.

    :param value: Inserted text to be centered.
    :param length: Total separator length.
    :param char: Separator character.
    """
    output = value

    # If no value passed, output separator of length.
    if value == None or len(value) == 0:
    output = f'{char * length}'
    elif len(value) < length:
    # Update length based on insert length, less a space for margin.
    length -= len(value) + 2
    # Halve the length and floor left side.
    left = math.floor(length / 2)
    right = left
    # If odd number, add dropped remainder to right side.
    if length % 2 != 0:
    right += 1

    # Surround insert with separators.
    output = f'{char * left} {value} {char * right}'

    cls.__output(output)

    @classmethod
    def log(cls, *args, sep: str = ' ', end: str = 'n', file=None):
    """Prints the passed value(s) to the console.

    :param args: Values to output.
    :param sep: String inserted between values, default a space.
    :param end: String appended after the last value, default a newline.
    :param file: A file-like object (stream); defaults to the current sys.stdout.
    """
    cls.__output(*args, sep=sep, end=end, file=file)

    @classmethod
    def log_exception(cls, exception: BaseException, expected: bool = True):
    """Prints the passed BaseException to the console, including traceback.

    :param exception: The BaseException to output.
    :param expected: Determines if BaseException was expected.
    """
    output = "[{}] {}: {}".format('EXPECTED' if expected else 'UNEXPECTED', type(exception).__name__, exception)
    cls.__output(output)
    exc_type, exc_value, exc_traceback = sys.exc_info()
    traceback.print_tb(exc_traceback)

    When Should You Use It?

    The seemingly simple import statement found in Python is actually rather complex when looking under the hood. At the most basic level an import statement is used to perform two tasks. First, it attempts to find the module specified by name, then loads and initializes it, if necessary. It also automatically defines a name in the local namespace within the scope of the associated import statement. This local name can then be used to reference the the accessed module throughout the following scoped code.

    While the import statement is the most common technique used to gain access to code from other modules, Python also provides other methods and functions that makeup the built-in import system. Developers can opt to use specific functions to have more fine-grained control over the import process.

    For our code samples we’ll stick to the common import statement that most of us are accustomed to. As mentioned in the introduction, behavior for failed imports differs depending on the Python version. To illustrate we start with the outer_import_2.7.py file:

    # outer_import_2.7.py
    import sys
    import gw_utility.Book

    def main():
    try:
    print(sys.version)
    except ImportError as error:
    # Output expected ImportErrors.
    print(error.__class__.__name__ + ": " + error.message)
    except Exception as exception:
    # Output unexpected Exceptions.
    print(exception, False)
    print(exception.__class__.__name__ + ": " + exception.message)

    if __name__ == "__main__":
    main()

    The outer prefix for the file name indicates that we’re testing an «outer» or globally scoped import statement of gw_utility.Book. Executing this code produces the following output:

    Traceback (most recent call last):
    File "C:UsersGabeAppDataLocalJetBrainsToolboxappsPyCharm-Pch-0172.3968.37helperspydevpydevd.py", line 1599, in <module>
    globals = debugger.run(setup['file'], None, None, is_module)
    File "C:UsersGabeAppDataLocalJetBrainsToolboxappsPyCharm-Pch-0172.3968.37helperspydevpydevd.py", line 1026, in run
    pydev_imports.execfile(file, globals, locals) # execute the script
    File "D:/work/Airbrake.io/Exceptions/Python/BaseException/Exception/ImportError/outer_import_2.7.py", line 3, in <module>
    import gw_utility.Book
    ImportError: No module named Book

    The overall issue here is that the gw_utility.Book module doesn’t exist. In fact, the proper module is lowercase: gw_utility.book. Since the import statement is at the top of the file, it exists outside our try-except block, so the ImportError we get in the log is not caught — execution was terminated entirely when the error was raised.

    Alternatively, let’s see what happens if we move the import statement inside a try-except block, as seen in inner_import_2.7.py:

    # inner_import_2.7.py
    import sys

    def main():
    try:
    print(sys.version)
    import gw_utility.Book
    except ImportError as error:
    # Output expected ImportErrors.
    print(error.__class__.__name__ + ": " + error.message)
    except Exception as exception:
    # Output unexpected Exceptions.
    print(exception, False)
    print(exception.__class__.__name__ + ": " + exception.message)

    if __name__ == "__main__":
    main()

    Running this code — also using Python 2.7 — produces the same ImportError, but we’re able to catch it and perform further processing of the caught ImportError, if necessary:

    2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)]
    ImportError: No module named Book

    The ModuleNotFoundError was added in Python 3.6 as a subclass of ImportError and an explicit indication of the same kind of errors we’re seeing above in the 2.7 code. For example, let’s look at the outer import example in Python 3.6 with outer_import_3.6.py:

    # outer_import_3.6.py
    import sys
    import gw_utility.Book
    from gw_utility.logging import Logging

    def main():
    try:
    Logging.log(sys.version)
    except ImportError as error:
    # Output expected ImportErrors.
    Logging.log_exception(error)
    # Include the name and path attributes in output.
    Logging.log(f'error.name: {error.name}')
    Logging.log(f'error.path: {error.path}')
    except Exception as exception:
    # Output unexpected Exceptions.
    Logging.log_exception(exception, False)

    if __name__ == "__main__":
    main()

    Once again, here we’re performing the import outside the try-except block, so running this code halts execution and produces the following output:

    Traceback (most recent call last):
    File "C:UsersGabeAppDataLocalJetBrainsToolboxappsPyCharm-Pch-0172.3968.37helperspydevpydevd.py", line 1599, in <module>
    globals = debugger.run(setup['file'], None, None, is_module)
    File "C:UsersGabeAppDataLocalJetBrainsToolboxappsPyCharm-Pch-0172.3968.37helperspydevpydevd.py", line 1026, in run
    pydev_imports.execfile(file, globals, locals) # execute the script
    File "C:UsersGabeAppDataLocalJetBrainsToolboxappsPyCharm-Pch-0172.3968.37helperspydev_pydev_imps_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"n", file, 'exec'), glob, loc)
    File "D:/work/Airbrake.io/Exceptions/Python/BaseException/Exception/ImportError/outer_import_3.6.py", line 3, in <module>
    import gw_utility.Book
    ModuleNotFoundError: No module named 'gw_utility.Book'

    The cause of this error is the exact same as the 2.7 version, but with 3.6+ the more specific ModuleNotFoundError is now raised. Additionally, we can actually catch such errors if the import is executed within a try-except context:

    # inner_import_3.6.py
    import sys
    from gw_utility.logging import Logging

    def main():
    try:
    Logging.log(sys.version)
    import gw_utility.Book
    except ImportError as error:
    # Output expected ImportErrors.
    Logging.log_exception(error)
    # Include the name and path attributes in output.
    Logging.log(f'error.name: {error.name}')
    Logging.log(f'error.path: {error.path}')
    except Exception as exception:
    # Output unexpected Exceptions.
    Logging.log_exception(exception, False)

    if __name__ == "__main__":
    main()

    This code allows us to output the Python version and process the error:

    3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
    [EXPECTED] ModuleNotFoundError: No module named 'gw_utility.Book'
    error.name: gw_utility.Book
    error.path: None

    We’re also outputting the name and path attributes of the ImportError object, which were added in Python 3.3 to indicate the name of the module that was attempted to be imported, along with the path to the file that triggered the exception, if applicable. In this case our code is rather simple so, unfortunately, neither attribute is particularly useful.

    Airbrake’s robust error monitoring software provides real-time error monitoring and automatic exception reporting for all your development projects. Airbrake’s state of the art web dashboard ensures you receive round-the-clock status updates on your application’s health and error rates. No matter what you’re working on, Airbrake easily integrates with all the most popular languages and frameworks. Plus, Airbrake makes it easy to customize exception parameters, while giving you complete control of the active error filter system, so you only gather the errors that matter most.

    Check out Airbrake’s error monitoring software today and see for yourself why so many of the world’s best engineering teams use Airbrake to revolutionize their exception handling practices! Try Airbrake free with a 14-day free trial.

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

    Примечание. Если вы хотите поиграться с кодом, то вот репозиторий Github.

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

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

    • Модуль — один скрипт Python.
    • Пакет — набор модулей.

    Вот и вся разница! Просто, не правда ли?

    Что ж, теперь давайте начинать!

    [python_ad_block]

    Импорт в рамках одного каталога

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

    Для простоты давайте сначала создадим один каталог scripts в каталоге нашего проекта и добавим в него два модуля — example1.py и example2.py. Наша структура будет выглядеть так:

    Идея состоит в том, чтобы любая функция/переменная/класс, определенные в example1.py, были доступны в example2.py. Содержимое у нас будет таким:

    #example1.py
    MY_EX1_STRING = 'Welcome to Example1 module!'
    def yolo(x: int):
         print("You only LIve", x, "times.")

    Чтобы импортировать эти элементы в example2.py, сделаем следующее:

    #example2.py
    import example1
    # imported string
    print("The imported string is: ", example1.MY_EX1_STRING)
    # imported function
    example1.yolo(10)

    Как видно, доступ к элементам в импортированном модуле можно получить с помощью записи через точку — например, example1.yolo() или example1.MY_EX1_STRING. Если вам покажется, что каждый раз писать example1.XXX утомительно, можно воспользоваться псевдонимом (созданным при помощи as) и переписать example2.py следующим образом:

    #example2.py
    import example1 as e1
    # imported string
    print("The imported string is: ", e1.MY_EX1_STRING)
    # imported function
    e1.yolo(10)

    Как вы правильно догадались, вывод останется прежним.

    Но что именно происходит, когда мы пишем оператор import?

    Интерпретатор Python пытается найти в sys.path каталог с модулем, который мы пытаемся импортировать. sys.path — это список каталогов, в которых Python будет искать после просмотра кэшированных модулей и модулей стандартной библиотеки Python.

    Давайте посмотрим, что в данный момент содержит наш системный путь sys.path (предварительно закомментировав предыдущие строки кода в example2.py).

    #example2.py
    # import example1
    # print("The imported string is: ", example1.MY_EX1_STRING)
    # example1.yolo(10)
    import sys
    print(sys.path)

    Как видите, самый первый элемент в полученном списке sys.path указывает на каталог Medium_Imports_Tutorial/scripts, в котором находится наш импортированный модуль, т. е. example1.py. Имейте в виду: то, что этот каталог волшебным образом присутствует в sys.path, не случайно.

    Вывод из sys.path всегда будет содержать текущий каталог с индексом 0! Текущий каталог — это тот, в котором находится запускаемый скрипт.

    Поэтому, когда и вызывающий, и вызываемый модули находятся в одном каталоге, импорт довольно прост.

    Что делать, если нужно импортировать только определенные элементы из модуля?

    В нашем примере в модуле example1.py определены только переменная типа string и функция. Важно помнить, что всякий раз, когда выполняется оператор импорта, будет запущен весь модуль. Чтобы доказать это, давайте немного изменим example1.py:

    #example1.py
    print("Thanks for importing Example1 module.")
    MY_EX1_STRING = 'Welcome to Example1 module!'
    def yolo(x: int):
         print("You only LIve", x, "times.")
    yolo(10000)

    А теперь попробуйте запустить example2.py. Вы увидите, что вместе с выводом оператора print() также выведется yolo(10000).

    Примечание. Существует обходной путь, с помощью которого мы можем контролировать, будет ли оператор выполняться при импорте. 

    #example1.py
    print("Thanks for importing Example1 module.")
    MY_EX1_STRING = 'Welcome to Example1 module!'
    def yolo(x: int):
         print("You only LIve", x, "times.")
    if __name__ == '__main__':
         yolo(10000)

    Код внутри оператора if__name__ == '__main__' не будет выполняться при импорте, но yolo() и MY_EX1_STRING, определенные снаружи, готовы к использованию через импорт. При этом, если бы мы запустили example1.py как автономный модуль, код внутри оператора if был бы выполнен.

    Итак, мы увидели, что импорт модуля запускает все его содержимое (если не использовать if __name__ == «__main__»). Теперь должно быть довольно понятно, почему импорт только интересующих элементов имеет смысл. Давайте посмотрим, как это сделать в example2.py. Для этого импортируем из example1.py только функцию yolo(). Это также поможет нам избавиться от записи через точку, и мы сможем просто использовать функцию yolo().

    #example2.py
    from example1 import yolo
    yolo(10)

    Точно так же мы могли бы написать from example1 import yolo, MY_EX1_STRING, чтобы импортировать оба объекта из example1.py.

    Примечание. В коде часто можно увидеть такие импорты, как from example1 import *. По сути, это означает импорт всего. Но это считается плохой практикой, поскольку негативно влияет на читабельность кода.

    Зачем нужен PYTHONPATH?

    Возможно, вы замечали, что в структуре каталогов проектов на GitHub часто бывает каталог utils. Он содержит служебные скрипты для распространенных задач, таких как предварительная обработка и очистка данных. Они хранятся отдельно от основных сценариев и предназначены для многократного использования.

    Давайте создадим такой каталог для нашего проекта.

    Пакет utils будет содержать три модуля — length.py, lower.py и upper.py для возврата длины строки и строк в нижнем и верхнем регистре соответственно.

    Также создадим модуль example3_outer.py в корне проекта. Сюда мы будем импортировать модули из пакета utils.

    Содержимое трех модулей будет следующим:

    #utils/length.py
    def get_length(name: str):
        return len(name)
    #utils/lower.py
    def to_lower(name: str):
        return name.lower()
    #utils/upper.py
    def to_upper(name: str):
        return name.upper()

    Теперь, чтобы импортировать модуль length.py в example3_outer.py, пишем следующее:

    #example3_outer.py
    import utils.length
    res = utils.length.get_length("Hello")
    print("The length of the string is: ",res)

    Важно отметить, что если бы мы выполнили импорт length вместо импорта utils.length, мы получили бы ModuleNotFoundError: No module named ‘length’. Это связано с тем, что список sys.path пока не содержит каталога ../Medium_Imports_Tutorial/utils, который необходим для поиска модуля length.py. Давайте посмотрим, как мы можем добавить его в этот список.

    Есть два способа сделать это.

    Способ 1: использование sys.path.append

    #example3_outer.py
    import os
    import sys
    fpath = os.path.join(os.path.dirname(__file__), 'utils')
    sys.path.append(fpath)
    print(sys.path)
    import length
    txt = "Hello"
    res_len = length.get_length(txt)
    print("The length of the string is: ",res_len)

    Несколько вещей, которые следует учесть:

    1. Порядок импорта важен. Мы сможем выполнить import length только после добавления пути к каталогу utils с помощью sys.path.append

    Короче говоря, не поддавайтесь искушению объединить import os, import sys и import length в верхней части скрипта только для аккуратности!

    2. os.path.dirname(__file__) возвращает абсолютный путь к текущему рабочему каталогу. Мы используем os.path.join, чтобы добавить каталог utils к этому пути.

    3. Как всегда, доступ к функциям, определенным в импортированном модуле, упрощается с помощью записи через точку, т.е. length.get_length().

    Способ 2: использование переменной окружения PYTHONPATH

    Однако зачастую проще изменить переменную PYTHONPATH, чем возиться с добавлением каталогов, как мы это только что делали.

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

    Прежде чем изменить PYTHONPATH, давайте проверим его содержимое при помощи команды echo $PYTHONPATH в терминале (чтобы случайно не перезаписать):

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

    С установленной переменной PYTHONPATH нам больше не нужно добавлять каталог к sys.path в example3_outer.py (мы закомментировали этот код в приведенном ниже фрагменте для ясности).

    #example3_outer.py
    #import os
    #import sys
    #fpath = os.path.join(os.path.dirname(__file__), 'utils')
    #sys.path.append(fpath)
    #print(sys.path)
    import length
    txt = "Hello"
    res_len = length.get_length(txt)
    print("The length of the string is: ",res_len)

    Примечание. Как только вы закроете python, список вернется к предыдущим значениям по умолчанию. Если вы хотите добавить каталог в PYTHONPATH навсегда, добавьте команду экспорта (export PYTHONPATH=$PYTHONPATH:$(pwd)/utils) в файл ~/.bashrc. (подробнее можно почитать обсуждение на StackOverflow).

    Наконец, познакомившись с обоими методами, давайте выберем один (в зависимости от ваших предпочтений и нужд) для импорта оставшихся двух модулей — upper.py и lower.py в example3_outer.py.

    P.S. Мы воспользуемся методом 1 просто для удовольствия 😉

    #example3_outer.py
    import os
    import sys
    fpath = os.path.join(os.path.dirname(__file__), 'utils')
    sys.path.append(fpath)
    import length
    import upper
    import lower
    txt = "Hello"
    res_len = length.get_length(txt)
    print("The length of the string is: ",res_len)
    res_up = upper.to_upper(txt)
    print("Uppercase txt: ", res_up)
    res_low = lower.to_lower(txt)
    print("Uppercase txt: ", res_low)

    Супер! Это выглядит потрясающе. Однако было бы здорово, если бы мы могли просто выполнить команду import utils вместо того, чтобы импортировать все модули по отдельности. В конце концов, наш случай использования предполагает, что нам нужны все три функции. Итак, как это сделать?

    Когда нам нужен __init__.py?

    Во-первых, давайте попробуем импортировать каталог utils в файле example3_outer.py (предварительно закомментировав весь существующий код):

    #example3_outer.py
    import utils

    Запуск этого скрипта не вызовет никакой ошибки, и это правильно — интерпретатор заглянет внутрь sys.path и найдет текущий каталог ../Medium_Imports_Tutorial с индексом 0. Это все, что ему нужно, чтобы найти каталог utils.

    Теперь попробуем получить доступ к модулю length.py из utils:

    #example3_outer.py
    import utils
    txt = "Hello"
    res = utils.length.get_length(txt)

    Попытавшись запустить этот скрипт, вы увидите AttributeError: module ‘utils’ has no attribute ‘length’. Это означает, что мы не сможем получить доступ к каким-либо скриптам Python внутри utils просто потому, что интерпретатор еще не знает, что это пакет!

    Мы можем превратить этот каталог в пакет, добавив файл __init__.py в папку utils следующим образом:

    В __init__.py мы импортируем все модули, которые, по нашему мнению, необходимы для нашего проекта.

    # utils/__init__.py (incorrect way of importing)
    from length import get_length
    from lower import to_lower
    from upper import to_upper

    И сделаем вызов в example3_outer.py.

    import utils
    txt = "Hello"
    res_low = utils.to_lower(txt)
    print(res_low)

    Подождите секунду! Почему мы видим ошибку при запуске example3_outer.py?

    Ошибки импорта

    То, как мы импортировали модули в __init__.py, может показаться логичным. Ведь __init__.py и length.py (или lower.py, upper.py) находятся на одном уровне, так что нет ни одной причины, чтобы from lower import to_lower не сработал. На самом деле, если вы запустите этот файл инициализации сам по себе, он будет выполняться безупречно (он не даст никаких результатов, но, тем не менее, будет успешно выполнен).

    Но при этом мы не можем использовать описанный выше способ импорта, потому что, хотя length.py и lower.py находятся на том же уровне, что и __init__.py, это не тот уровень, с которого будет вызываться init.

    В действительности, мы делаем вызов из example3_outer.py, поэтому для поиска любого импорта в sys.path будет только текущий каталог example3_outer.py, т.е. ../Medium_Imports_Tutorial.

    Когда интерпретатор встречает команду import utils в файле example3_outer.py, даже если он переходит к __init__.py внутри каталога utils, sys.path не обновляется автоматически, и, следовательно, интерпретатор не может узнать, где найти модуль с именем length.

    Мы должны как-то указать на расположение каталога utils. Для этого мы можем использовать относительный или абсолютный импорт в __init__.py (или установить переменную PYTHONPATH, как это было описано выше).

    Относительный импорт

    Мы не рекомендуем использовать относительный импорт, но для общего развития давайте посмотрим, как он работает. Тут нужно указать путь относительно пути вызывающего скрипта. Выглядеть это будет так:

    # utils/__init__.py
    from .lower import to_lower
    from .upper import to_upper
    from .length import get_length

    При указании относительного импорта мы используем запись через точку (. или ..). Одиночная точка перед lower указывает на тот же каталог, из которого вызывается импорт. Это можно представить как импорт функции to_lower() из ./lower.py. Пара точек перед названием модуля означает переход на два уровня вверх от текущего.

    Абсолютный импорт

    Абсолютный импорт более предпочтителен. Вы указываете абсолютный путь к импортируемому модулю из корня проекта (или любого другого каталога, к которому имеет доступ sys.path):

    # utils/__init__.py
    from utils.lower import to_lower
    from utils.upper import to_upper
    from utils.length import get_length

    Теперь у программы есть гораздо больше информации по сравнению с относительным импортом. Более того, она менее подвержена взлому. sys.path имеет доступ к корню проекта, т. е. ../Medium_Imports_Tutorial, как описано выше, и оттуда он может легко найти каталог utils. (Почему? Потому что это непосредственный дочерний каталог корня проекта).

    Что происходит, когда мы импортируем пакет с определенным __init__.py? 

    Это работает как шаг инициализации. __init__.py — первый файл, который будет выполняться при импорте пакета. Учитывая, что здесь мы делаем весь необходимый импорт, код в вызывающем скрипте становится намного чище. К примеру, example3_outer.py будет выглядеть так:

    #example3_outer.py
    import utils
    txt = "Hello"
    res_len = utils.get_length(txt)
    print(res_len)
    res_up = utils.to_upper(txt)
    print(res_up)
    res_low = utils.to_lower(txt)
    print(res_low)

    Потрясающе! Мы преобразовали наш каталог utils в пакет. Прелесть этого пакета в том, что его можно импортировать куда угодно и использовать практически сразу. Давайте посмотрим, как мы можем использовать этот пакет внутри каталога scripts. Для этого создадим новый файл с именем example3.py в scripts.

    # scripts/example3.py
    import os
    import sys
    PROJECT_ROOT = os.path.abspath(os.path.join(
                      os.path.dirname(__file__), 
                      os.pardir)
    )
    sys.path.append(PROJECT_ROOT)
    
    import utils
    print(utils.get_length("Hello"))
    ************** OUTPUT *********
    5

    Несколько вещей, которые следует учитывать:

    • Перед импортом пакета utils мы должны убедиться, что родительский каталог utils, т.е. корень проекта, доступен для интерпретатора Python. Было бы неосмотрительно предполагать, что это произойдет по умолчанию, в основном потому, что мы сейчас находимся на один уровень ниже корневого каталога проекта (мы запускаем скрипт из scripts/example3.py), и в sys.path под индексом 0 будет ../Medium/Imports_Tutorial/scripts.
    • os.path.dirname(__file__) даст имя каталога для текущего скрипта, а os.pardir даст путь к родительскому каталогу, используя точечную нотацию, т.е. .. . В общем, os.path.abspath будет предоставлять абсолютный путь к корню проекта.

    Бонус: мы даже можем добавлять в наш __init__.py модули из других каталогов. Например, давайте добавим yolo(), определенный в scripts/example1.py.

    # utils/__init__.py
    from utils.lower import to_lower
    from utils.upper import to_upper
    from utils.length import get_length
    from scripts.example1 import yolo

    Вызов этой функции в example3.py будет выглядеть следующим образом:

    # scripts/example3.py
    import os
    import sys
    PROJECT_ROOT = os.path.abspath(os.path.join(
                      os.path.dirname(__file__), 
                      os.pardir)
    )
    sys.path.append(PROJECT_ROOT)
    import utils
    print(utils.get_length("Hello"))
    utils.yolo(2)
    ************** OUTPUT *********
    5
    You only LIve 2 times.

    Заключение

    Итак, сегодня мы обсудили, как импортировать в Python. Честно говоря, поначалу ошибки импорта действительно пугают, потому что это та область, о которой не так много говорят. Однако есть один полезный прием: какой бы пакет/модуль вы ни пытались импортировать с помощью import XYZ, убедитесь, что интерпретатор Python имеет к нему доступ. Если нет, обновите sys.path или, что еще лучше, добавьте соответствующий каталог в переменную PYTHONPATH.

    Надеемся, данная статья была полезна для вас! Успехов в написании кода!

    Перевод статьи «Understanding Python imports, __init__.py and pythonpath — once and for all».

    It is __init__.py not init.py. Make sure each of the directory in hierarchy contains it in order to be able to import.

    EDIT: I managed to reproduce it.
    Here’s the directory structure:

    cesar@cesar-laptop:/tmp/asdasd$ tree
    .
    `-- myapp
        |-- __init__.py
        |-- models
        |   |-- __init__.py
        |   `-- models.py
        |-- scripts
        |   |-- data.py
        |   `-- __init__.py
        `-- tests
            |-- __init__.py
            `-- tests.py
    

    I put the following code at the very beginning of the data.py to narrow down the problem:

    import sys
    import pprint
    
    pprint.pprint(sys.path)
    
    from myapp.models.models import *
    

    Running the data.py the way OP indicated yeilds ImportError:

    cesar@cesar-laptop:/tmp/asdasd$ python myapp/scripts/data.py
    ['/tmp/asdasd/myapp/scripts',
     '/usr/lib/python2.6',
     '/usr/lib/python2.6/plat-linux2',
     '/usr/lib/python2.6/lib-tk',
     -- Skipped --
    '/usr/local/lib/python2.6/dist-packages']
    Traceback (most recent call last):
      File "myapp/scripts/data.py", line 6, in 
        from myapp.models.models import *
    ImportError: No module named myapp.models.models
    

    But this way works like a charm:

    cesar@cesar-laptop:/tmp/asdasd$ python -m myapp.scripts.data
    ['',
     '/usr/lib/python2.6',
     '/usr/lib/python2.6/plat-linux2',
     '/usr/lib/python2.6/lib-tk',
     -- Skipped --
    '/usr/local/lib/python2.6/dist-packages']
    

    Note the difference in the first entry of sys.path.

    ModuleNotFoundError: no module named Python Error [Fixed]

    When you try to import a module in a Python file, Python tries to resolve this module in several ways. Sometimes, Python throws the ModuleNotFoundError afterward. What does this error mean in Python?

    As the name implies, this error occurs when you’re trying to access or use a module that cannot be found. In the case of the title, the «module named Python» cannot be found.

    Python here can be any module. Here’s an error when I try to import a numpys module that cannot be found:

    import numpys as np
    

    Here’s what the error looks like:

    image-341

    Here are a few reasons why a module may not be found:

    • you do not have the module you tried importing installed on your computer
    • you spelled a module incorrectly (which still links back to the previous point, that the misspelled module is not installed)…for example, spelling numpy as numpys during import
    • you use an incorrect casing for a module (which still links back to the first point)…for example, spelling numpy as NumPy during import will throw the module not found error as both modules are «not the same»
    • you are importing a module using the wrong path

    How to fix the ModuleNotFoundError in Python

    As I mentioned in the previous section, there are a couple of reasons a module may not be found. Here are some solutions.

    1. Make sure imported modules are installed

    Take for example, numpy. You use this module in your code in a file called «test.py» like this:

    import numpy as np
    
    arr = np.array([1, 2, 3])
    
    print(arr)
    

    If you try to run this code with python test.py and you get this error:

    ModuleNotFoundError: No module named "numpy"
    

    Then it’s most likely possible that the numpy module is not installed on your device. You can install the module like this:

    python -m pip install numpy
    

    When installed, the previous code will work correctly and you get the result printed in your terminal:

    [1, 2, 3]
    

    2. Make sure modules are spelled correctly

    In some cases, you may have installed the module you need, but trying to use it still throws the ModuleNotFound error. In such cases, it could be that you spelled it incorrectly. Take, for example, this code:

    import nompy as np
    
    arr = np.array([1, 2, 3])
    
    print(arr)
    

    Here, you have installed numpy but running the above code throws this error:

    ModuleNotFoundError: No module named "nompy"
    

    This error comes as a result of the misspelled numpy module as nompy (with the letter o instead of u). You can fix this error by spelling the module correctly.

    3. Make sure modules are in the right casing

    Similar to the misspelling issue for module not found errors, it could also be that you are spelling the module correctly, but in the wrong casing. Here’s an example:

    import Numpy as np
    
    arr = np.array([1, 2, 3])
    
    print(arr)
    

    For this code, you have numpy installed but running the above code will throw this error:

    ModuleNotFoundError: No module named 'Numpy'
    

    Due to casing differences, numpy and Numpy are different modules. You can fix this error by spelling the module in the right casing.

    4. Make sure you use the right paths

    In Python, you can import modules from other files using absolute or relative paths. For this example, I’ll focus on absolute paths.

    When you try to access a module from the wrong path, you will also get the module not found here. Here’s an example:

    Let’s say you have a project folder called test. In it, you have two folders demoA and demoB.

    demoA has an __init__.py file (to show it’s a Python package) and a test1.py module.

    demoA also has an __init__.py file and a test2.py module.

    Here’s the structure:

    └── test
        ├── demoA
            ├── __init__.py
        │   ├── test1.py
        └── demoB
            ├── __init__.py
            ├── test2.py
    

    Here are the contents of test1.py:

    def hello():
      print("hello")
    

    And let’s say you want to use this declared hello function in test2.py. The following code will throw a module not found error:

    import demoA.test as test1
    
    test1.hello()
    

    This code will throw the following error:

    ModuleNotFoundError: No module named 'demoA.test'
    

    The reason for this is that we have used the wrong path to access the test1 module. The right path should be demoA.test1. When you correct that, the code works:

    import demoA.test1 as test1
    
    test1.hello()
    # hello
    

    Wrapping up

    For resolving an imported module, Python checks places like the inbuilt library, installed modules, and modules in the current project. If it’s unable to resolve that module, it throws the ModuleNotFoundError.

    Sometimes you do not have that module installed, so you have to install it. Sometimes it’s a misspelled module, or the naming with the wrong casing, or a wrong path. In this article, I’ve shown four possible ways of fixing this error if you experience it.

    I hope you learned from it :)



    Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started

    Понравилась статья? Поделить с друзьями:
  • Ошибка инвертора кромочный станок holzher
  • Ошибка импорта ошибка при парсинге
  • Ошибка инвертора ol2
  • Ошибка импорта открытого ключа
  • Ошибка импорта музыки код ошибки 80 3utools