# Import
모든 코드를 하나의 파일에 넣으면 금방 관리하기 힘들어져요. 
`import` 문은 다른 파일에서 함수와 전역 변수를 가져올 수 있게 해줘요.
한 장의 스크린샷으로 보는 작동 방식:
![](ImportsInOnePicture400)

여기서 `import module2`는 `module2`라는 이름의 파일을 실행하고 그 파일의 모든 전역 변수에 접근할 수 있게 해줘요.
그런 다음 `.` 연산자를 사용하여 import된 모듈 안의 변수와 함수에 접근할 수 있어요.
그래서 이 예시에서, `module2.print_x()`는 `module2` 안에 있는 `print_x()`를 호출해요.

### 여기까지 읽어도 괜찮아요

`from` 구문을 사용해서 import된 모듈의 전역 변수들을 import 문이 실행되는 현재 스코프로 옮길 수도 있어요.

`from module2 import print_x
print_x()`
`module2`에서 지정된 전역 변수만 import해요.

또는

`from module2 import *
print_x()`
`module2`의 모든 전역 변수를 import해요.

이 방법도 `module2` 파일을 import하지만, `module2`라는 이름의 변수를 통해 접근하는 대신 `module2`의 전역 변수들을 풀어서 지역 스코프에 직접 할당해요.

이런 형태의 import는 보통 권장되지 않아요. 두 파일이 서로를 import할 때 잘 작동하지 않고, 이름 충돌 때문에 import하는 파일의 변수를 실수로 덮어쓸 수도 있거든요. 뭘 하는지 잘 모를 때는 `from` 구문을 피하는 것이 더 안전해요.

# 실제 작동 원리

## 요약
Import는 꽤 직관적이지 않을 수 있지만, 대부분의 문제는 `from file import` 대신 `import file` 구문을 고수하고, 전역 정의가 아닌 모든 것을
`if __name__ == "__main__":`
으로 감싸면 피할 수 있어요.

## Import의 사이드 이펙트
파일을 처음 import하면, 파일 전체가 실행된 다음 실행 중에 정의된 모든 변수에 접근할 수 있게 돼요.
같은 파일을 다시 import하면, 처음 import했을 때 캐시된 모듈을 다시 반환할 뿐이에요.

이것은 import 문이 사이드 이펙트를 가질 수 있다는 뜻이에요. 만약 `harvest()`를 호출하는 파일을 import하면, import하는 동안 실제로 수확을 할 거예요. 하지만 다시 import할 때는 파일이 한 번만 실행되기 때문에 다시 수확하지 않아요.

`__name__` 변수를 사용해서 이런 사이드 이펙트를 피할 수 있는 방법이 있어요. 이 변수는 파일이 직접 실행될 때는 자동으로 `"__main__"`으로 설정되고, `import`를 통해 실행될 때는 파일 이름으로 설정돼요.
파일이 import될 때 실행하고 싶지 않은 코드는 `if __name__ == "__main__":` 블록 안에 넣는 것이 좋은 습관으로 여겨져요.

Python의 일반적인 파일 구조는 파일이 실행될 때 실행되어야 할 코드를 `main()` 함수에 넣는 것이에요. 이렇게 하면 지역 변수(`main()` 안에 정의됨)와 import할 수 있는 전역 변수(`main()` 밖에 정의됨)를 명확하게 구분할 수 있어요.

`a_global_variable = "global"

def main():
    a_local_variable = "local"
    # do things

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

## 순환 Import
만약 파일 `a`가 파일 `b`를 import하고 파일 `b`가 파일 `a`를 import하면 어떻게 될까요?

파일 `a`:
`import b
x = 0`

파일 `b`:
`import a
def f():
    print(a.x)`

이건 문제없이 작동할 거예요. 두 파일 모두 아직 로드되지 않았고, 다른 누군가가 `import a`를 실행한다고 가정해봐요.

-`a`는 `import b` 줄까지 실행돼요.
-`b`는 `import a` 줄까지 실행돼요.
-모듈 `a`는 이미 존재하지만, 아직 `import b` 줄까지만 도달했기 때문에 `x`를 포함하고 있지 않아요.
-`b`는 반쯤 로드된 모듈 `a`에 대한 참조를 `a`라는 변수에 저장해요.
-`b`는 `def` 문을 실행하고 `f()` 함수를 저장해요.
-`a`는 계속 실행되어 `x`를 초기화해요.

누군가 `b.f()`를 호출하면 `b`가 참조하는 모듈 `a`가 이제 완전히 로드되었기 때문에 `0`이 올바르게 출력될 거예요.

이제 `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` 줄에 도달하지 않았기 때문에 아무것도 포함하고 있지 않아서, 아무것도 import되지 않아요.
-`b`는 `def` 문을 실행하고 `f()` 함수를 저장해요.
-`a`는 계속 실행되어 `x`를 초기화해요.

이제 누군가 `b.f()`를 호출하면, 현재 스코프에 `x`가 존재하지 않는다는 오류가 발생할 거예요. 이번에는 `b`가 아직 로드 중인 `a`에 대한 참조를 가지고 있지 않고, import 후에 추가된 정의를 볼 수 없기 때문이에요.