Python import file with imports

Python 3: Import Another Python File as a Module

In Python, a module is a single unit of Python code that can be imported (loaded and used) by other Python code. A module can contain definitions (like functions and constants), as well as statements that initialize those definitions. Once the module code is written, it can be reused by any script that imports the module.

A common way to create a Python module is to create a file with a filename that ends in .py , and write the module code in there. If we use a different file extension in the filename, or no extension at all, the standard import statements shown below will not work, and we’ll have to use importlib instead, which requires more code (more info below).

To illustrate standard import usage, let’s say we create a file called mymodule.py with the following function definition:

def say_hello(): print( 'Hello, world!' )

Now every time we want to write «Hello, world!» to the screen from a Python script, we can simply import this module rather than having to write the message again. It also allows us to change one line of code inside mymodule.py rather than in many different scripts if we ever decide to change the message we want to show in all the scripts that use this function.

Читайте также:  Javascript get span width

Import a File in the Same Directory

Let’s say we have two Python files in the same directory:

mymodule.py contains the say_hello() function we saw above.

To call say_hello() from inside script.py , we can write in script.py :

import mymodule mymodule.say_hello()

The name used in the import statement is simply the module’s filename without the .py extension at the end.

Import a File in a Subdirectory (Python 3.3 and Up)

Python versions 3.3 and higher allow easy imports of modules in subdirectories of the current script’s directory. If you’re using a Python version lower than 3.3, you can follow the steps in Import a File in a Different Directory instead.

Let’s say we move mymodule.py to a subdirectory called subdir :

Then if we’re using Python 3.3 or higher, we can write in script.py :

import subdir.mymodule subdir.mymodule.say_hello()

In a file system path, we would separate the components of a path using / (Linux, macOS, etc.) or \ (Windows). In a Python import statement, however, we separate the path components using a dot ( . ).

We can also assign a shorter name for the module using an import — as statement:

import subdir.mymodule as m m.say_hello()

where m is any name we choose. We can also import the function directly:

from subdir.mymodule import say_hello say_hello()

This works even if there are multiple levels of subdirectories. For example, if we had the following directory structure:

we could write in script.py :

import alpha.beta.mymodule as mymodule mymodule.say_hello()

Import a File in a Different Directory

Now let’s say that we move mymodule.py to a directory that is outside of the current directory tree:

By default, Python looks for files in the same directory (including subdirectories) as the current script file, as well as in other standard locations defined in sys.path . If you’re curious what these locations are, you can print out the sys.path variable like this:

import sys for p in sys.path: print( p )

However, if the file we want to import is somewhere else entirely, we’ll first have to tell Python where to look by adding search directories to sys.path . In our example, we can write in script.py :

import sys sys.path.append( '/alpha/beta' ) import mymodule mymodule.say_hello()

Note that the path appended to sys.path is an absolute path. If we used a relative path, the path would resolve differently based on the directory from which the user is running the script, not relative to script.py ‘s path.

To append a directory relative to this script file, you can use __file__ to get the current script’s full path and build a full path to the import from there. In script.py we can write:

import os import sys script_dir = os.path.dirname( __file__ ) mymodule_dir = os.path.join( script_dir, '..', 'alpha', 'beta' ) sys.path.append( mymodule_dir ) import mymodule mymodule.say_hello()

Import Any File, Including Non- .py File Extension (Python 3.4 and Up)

Absolute Path

Python versions 3.4 and higher provide functionality through the built-in importlib library that allows us to load any file anywhere as a Python module, even if the file’s filename does not end in .py (it can have a different file extension, or no file extension at all).

For example, let’s say we have the following directory structure:

Notice here that the mymodule filename does not have a file extension. In this case, we can’t use a simple import statement to import that file. Instead, we can write in script.py :

import importlib.machinery import importlib.util # Import mymodule loader = importlib.machinery.SourceFileLoader( 'mymodule', '/alpha/beta/mymodule' ) spec = importlib.util.spec_from_loader( 'mymodule', loader ) mymodule = importlib.util.module_from_spec( spec ) loader.exec_module( mymodule ) # Use mymodule mymodule.say_hello()

Note that the path passed into SourceFileLoader() is an absolute path. If we used a relative path like ../alpha/beta/mymodule , the path would resolve differently based on the directory from which the user is running the script, not relative to script.py ‘s path.

Relative Path

If we want to reference a file relative to our current script file’s path, we can use __file__ to first get our current script file’s path, and then build a full path from there:

import importlib.machinery import importlib.util from pathlib import Path # Get path to mymodule script_dir = Path( __file__ ).parent mymodule_path = str( script_dir.joinpath( '..', 'alpha', 'beta', 'mymodule' ) ) # Import mymodule loader = importlib.machinery.SourceFileLoader( 'mymodule', mymodule_path ) spec = importlib.util.spec_from_loader( 'mymodule', loader ) mymodule = importlib.util.module_from_spec( spec ) loader.exec_module( mymodule ) # Use mymodule mymodule.say_hello()

References

Источник

Python import, как и для чего?

В языке программирования Python подключение пакетов и модулей осуществляется с помощью import. Это позволяет распределять код по логическим «узлам» приложения(модели данных, обработчики, и тп.), что позволяет получить менее нагруженные кодом файлы.

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

Как использовать import?

Синтаксис import в Python достаточно прост и интуитивно понятен:

# В данной строке импортируется something_we_want import something_we_want # В данной строке импортируется something_we_want, как aww(логично и просто) import something_we_want as aww # В данной строке импортируется из something_we_want something(логично и просто) from something_we_want import something # В данной строке импортируется из something_we_want something, как s(логично и просто) from something_we_want import something as s # Синтаксис as позволяет обращаться к импортируемому по новому нами описанному # далее имени(это работает только в рамках нашего файла)

Что можно импортировать?

Для более глубокого понимания import стоит рассмотреть пример, представленный ниже.

def something(): pass somedata = 5
# 1 случай import something_we_want something_we_want.something() import something_we_want print(something_we_want.somedata) # 2 случай import something_we_want as aww aww.something() import something_we_want as aww print(aww.somedata) # 3 случай from something_we_want import something something() from something_we_want import somedata print(somedata) # 4 случай from something_we_want import something as s s() from something_we_want import somedata as sd print(sd) # Классы импортируются по аналогии с функциями

Красиво, читаемо и понятно.

В чем же подвох?

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

Идеология Python достаточно интересна, что позволяет ему иметь низкий порог вхождения, низкое время написания кода, высокую читаемость, но именно в ней и кроется подвох.

По своему опыту использования данного языка, сложилось отчетливое ощущение главной идеи ООП(все есть объект). Что же в этом плохого?

Все файлы, функции и тд. это объект. Но что это за объект и класс стоят за файлами(модулями)?

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

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

Ветвистая структура приложения и существующие подходы импортирования

Часто в разработке приложений программисты пытаются разбить программу по логическим «узлам». Данный подход повышает читаемость и позволяет вести разработку в команде(один человек занимается реализацией одного «узла», второй другого). Так порождается структура приложения, которая зачастую виду сложности функционала является достаточно обширной(ветвистой, потому что имея одну точку входа откуда уже обрастая функционалом это становится похожим на дерево).

Пример ветвистой структуры:

Существует 2 подхода импортирования(лучше выбрать один и придерживаться его весь проект):

Пример именованного импорта из models.py в auth.py:

# auth.py from app.models import User

Пример неименованного импорта из models.py в auth.py:

# auth.py from ..models import User # Количество точек указывает на сколько (обьектов) мы поднимаемся от исходного. # В данном примере первая точка поднимает нас на уровень обьекта handlers, # А вторая точка поднимает нас на уровень обьекта app

Это два абсолютно разных подхода. В первом случае мы «идем» из «корня»(входной точки нашего приложения). Во втором случае мы «идем» от «листа»(нашего файла).

Плюсы и минусы подходов импорта:

Видна структура импорта и приложения.

Видна часть структуры импорта.

Программисту не нужно знать полную структуру приложения.

Импорт не зависит от точки входа.

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

Импорт зависит от точки входа.

Программисту необходимо знать структуру приложения. Код сильно связан с приложением. Что по сути усложняет отладку, тестирование, и тд. Программист становится сильно вовлеченным в проект.

Снижается читаемость импорта.

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

P.S.

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

Пишите тот код, который бы сами хотели получить от исполнителя.

Источник

Оцените статью