# Импорт
Хранить весь код в одном файле быстро станет неудобно.
Инструкция `import` позволяет импортировать функции и глобальные переменные из другого файла.
Принцип на одном скриншоте:
![](ImportsInOnePicture400)

Здесь `import module2` запускает файл с именем `module2` и дает доступ ко всем его глобальным переменным.
Затем ты можешь получить доступ к переменным и функциям внутри импортированного модуля, используя оператор `.`.
Так, в этом примере, `module2.print_x()` вызывает `print_x()` из `module2`.

### Дальше читать необязательно

Ты также можешь перенести глобальные переменные из импортированного модуля в текущую область видимости, где выполняется инструкция импорта, используя `from`.

`from module2 import print_x
print_x()`
Импортирует только указанные глобальные переменные из `module2`.

Или:

`from module2 import *
print_x()`
Импортирует все глобальные переменные из `module2`.

Так тоже можно импортировать файл `module2`. Но при этом ты не получишь к нему доступ через переменную с именем `module2`, а распакуешь глобальные переменные из `module2` и присвоишь их непосредственно в локальной области видимости.

Этот вид импорта обычно не рекомендуется, поскольку может создать неудобство, если два файла импортируют друг друга. Из-за совпадения имен можно случайно перезаписать переменные в импортирующем файле. Лучше избегать `from`, если ты не до конца понимаешь, что делаешь.

# Как импорт действует на самом деле

## TLDR
Импорт может показаться довольно неочевидным. Однако большинства проблем легко избежать, если использовать команду `import file` вместо `from file import` и оборачивать все, что не является определением глобальной переменной, в
`if __name__ == "__main__":`

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

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

Избежать подобных побочных эффектов можно с помощью переменной `__name__`. Это переменная, которой автоматически присваивается значение `"__main__"`, если файл запускается напрямую, и имя файла — если он запускается через `import`.
Любой код, который ты не хочешь выполнять при импорте файла, принято убирать внутрь блока `if __name__ == "__main__":`.

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

`a_global_variable = "global"

def main():
    a_local_variable = "local"
    # делает что-то

if __name__ == "__main__":
    main()`

## Циклические импорты
Что произойдет, если файл `a` импортирует файл `b`, а файл `b` импортирует файл `a`?

Файл `a`:
`import b
x = 0`

Файл `b`:
`import a
def f():
    print(a.x)`

Ничего страшного. Допустим, ни один из файлов еще не загружен, и кто-то выполняет `import a`.

- `a` выполняется до строки `import b`.
- `b` выполняется до строки `import a`.
- Модуль `a` уже существует, но не содержит `x`, потому что дошел только до строки `import b`.
- `b` сохраняет ссылку на наполовину загруженный модуль `a` в переменной с именем `a`.
- `b` выполняет инструкцию `def` и сохраняет функцию `f()`.
- `a` продолжает выполняться и инициализирует `x`.

Когда кто-то вызовет `b.f()`, он правильно выведет `0`, потому что модуль `a`, на который у `b` есть ссылка, теперь полностью загружен.

Рассмотрим тот же код с использованием `from`.

Файл `a`:
`from b import *
x = 0`

Файл `b`:
`from a import *
def f():
    print(x)`

- `a` выполняется до строки `from b import *`.
- `b` выполняется до строки `from a import *`.
- Модуль `a` уже существует, но еще не был выполнен полностью.
- `b` распаковывает все, что в данный момент есть в `a`, в собственную глобальную область видимости. На данный момент `a` ничего не содержит, потому что еще не достигнута строка `x = 0`, и ничего не импортируется.
- `b` выполняет инструкцию `def` и сохраняет функцию `f()`.
- `a` продолжает выполняться и инициализирует `x`.

Если кто-то теперь вызовет `b.f()`, то получит сообщение о том, что `x` не существует в текущей области видимости. Дело в том, что на этот раз у `b` нет ссылки на все еще загружающийся `a` и он не видит определений, которые были добавлены после импорта.