상대경로와 절대경로에서 어떤 경우에 import에러가 나타나는지 살펴보자.

 

 

상대경로: 내가 작업하는 위치를 기준으로 경로가 결정 

 

절대경로: 최상단 디렉토리를 기준으로 하는 경로이다. 어느 파일, 어느 위치에서든 경로가 항상 동일하다. 

 

 

 

 

import os

 

os.getcwd() #os 모듈의 getcwd()는 현재 디렉토리(작업폴더)를 알려줍니다.

 

#C:\Users\Jaesang Choi\Desktop\CALC 

 

 

 

 

calc/main.py

from .calculator.add_and_multiply import add_and_multiply
if __name__ == '__main__':
print(add_and_multiply(1,2))

 

calc/calculator/add_and_multiply.py

from .multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)

 

calc/calculator/multiplication.py

def multiply(a,b):
return(a*b)

 

 

 

 

 

 

 

calc/main.py

from .calculator.add_and_multiply import add_and_multiply
if __name__ == '__main__':
print(add_and_multiply(1,2))

main.py에서 상대경로로  add_and_multiply 함수를 import할 때 에러가 발생한다.

 

 

에러 로그는 다음과 같다.
'attempted relative import with no known parent package`'

 

 

 

 

다음과 같은 에러가 나오는 이유:

 

상대경로로 import를 할 땐 현재 module의 이름을 기반으로 한다.

 

그런데 현재 활성화된 메인 모듈의 이름은 항상 __main__이기 때문에 파이썬이 상대경로의 출발점,

메인모듈의 위치를 찾지 못하기 때문이다.

(만약에 apple.py모듈이 메인모듈이라면 그것도 역시 이름이 __main__으로 변경된다.)

 

if __name__ == '__main__':

    print(add_and_multiply(1,2)) 에서

 

  __name__ == "__main__"인걸 보면 알 수 있다.

 

 

 

그렇기 때문에 절대경로를 써야 이를 해결할 수 있다.

from calculator.add_and_multiply import add_and_multiply #절대경로로 변경
if __name__ == '__main__':
print(add_and_multiply(1,2))

현재 폴더의 경로는 C:\Users\Jaesang Choi\Desktop\CALC 이니까 그 다음에 올 경로만 쓰면 된다.

 

 

 

 

 

 

 

add_and_multiply.py는 상대경로로 쓰일 수 있다.

 

이유는 메인파일이 실행되고 나면 메인을 기준으로 절대경로가 잡히게 되는데,

이때 add_and_multiply는 경로내에서 calculator 패키지의 하위 모듈로 등록이 된다.

 

메인모듈의 절대경로가 잡히면서 다른 모듈들을 상대적으로(Relative) 비교할수 있는 뿌리가 생긴 것이다.

 

 

 

 

중요!) 따라서 메인파일에선 절대경로를, 그외의 하위모듈은 상대경로를 사용할 수 있게 된다.

 

 

 

 

 

 

add_and_multiply.py(상대경로)

from .multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)

 

 

 

add_and_multiply.py(절대경로) #절대경로로도 사용 할 수 있다.

from calculator.multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)

절대경로 가능

 

 

 

from multiplication import multiply
def add_and_multiply(a,b):
return multiply(a,b) + (a+b)

단 위와같은 절대경로로는 사용할 수 없다.

 

 

 

 

main.py 실행

add_and_multiply를 main모듈에 import할 때 절대경로를 써야한다.
(상대경로 쓸 시 에러.)


add_and_multiply에서 multiplication를 import할때 상대경로,절대경로 둘 다 가능하다.

 

add_and_multiply 직접실행 (이제 이 모듈이 메인모듈이 됨)
multiplication를 import할때 절대를 써주어야한다.
(상대경로 쓸 시 에러.)

 

 

 

 

 

TIL#36 하위,동일,상위파일 import하기

TIL#28 import error 상대경로 절대경로 상대경로와 절대경로에서 어떤 경우에 import에러가 나타나는지 살펴보자. import os print(os.path.abspath('.')) #현재 폴더의 절대경로를 물어보는 것 C:\Users\Jaesa..

higher77.tistory.com

 

 

 

참고자료:

https://velog.io/@hamsterhamin/Python-ImportError-attempted-relative-import-with-no-known-parent-package

https://livetodaykono.tistory.com/23

'Python > Today I learned' 카테고리의 다른 글

TIL#30 내장함수  (0) 2021.05.19
TIL#29 예외(exception)  (0) 2021.05.19
TIL#27 패키지와 import  (0) 2021.05.18
TIL#26 모듈과 import, sys.path  (0) 2021.05.18
TIL#25 클래스 와 인스턴스(중요)  (0) 2021.05.18

 

 

 

# 파이썬 패키지

패키지 작성 및 사용법

# 파이썬은 패키지로 분할 된 개별적인 모듈로 구성(모듈을 모아놓은 폴더를 패키지라고 생각하자.)


# __init__.py : 파이썬에게 이건 패키지라고 import해서 쓸 수 있다고 인식시켜주는 것
# Python3.3 부터는 없어도 패키지로 인식 -> 단, 하위 호환을 위해 작성 추천


상대 경로 : ..(부모 디렉토리), .(현재 디렉토리 [생략가능]) -> 모듈 내부에서만 사용

 

 

상대경로: 내가 작업하는 위치를 기준으로 경로가 결정

 

절대경로: 최상단 디렉토리를 기준으로 하는 경로이다. 어느 파일, 어느 위치에서든 경로가 항상 동일하다. 

 

 

 

 

module1.py

import sys
import inspect
def mod1_test1():
print ("Module1 -> Test1")
print("Path : ", inspect.getfile(inspect.currentframe()))
#현재 이 파일이 실행되는 경로를 표시해주는 메소드
def mod1_test2():
print ("Module1 -> Test2")
print("Path : ", inspect.getfile(inspect.currentframe()))

 

 

 

module2.py

import sys
import inspect
def mod2_test1():
print ("Module2 -> Test1")
print("Path : ", inspect.getfile(inspect.currentframe()))
def mod2_test2():
print ("Module2 -> Test2")
print("Path : ", inspect.getfile(inspect.currentframe()))

 

 

 

__init__.py (sub1폴더에 있는것)

__all__ = ['module1']
#__init__파일이 아예 비워졌으면 상관이 없지만
# all리스트 형식이 있으면 거기에 적혀있는 파일 이름을 허락한다.
#__all__ = ['module2','module3']이렇게 적혀있으면 module1이 없기 때문에 오류가 난다.

 

 

 

 

 

 

chapter06_03.py


# 예제1

import sub.sub1.module1
#append를 시키지 않아도 같은 경로나 또는 다른 위치에 있는 것들을 찾아갈 수 있다.
#sub패키지 안에 sub1이라는 패키지 안에 모여있는 모듈 중에서 module1을 가지고 와라
import sub.sub2.module2
# 사용
sub.sub1.module1.mod1_test1()
#Module1 -> Test1
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub1/module1.py
sub.sub1.module1.mod1_test2()
#Module1 -> Test2
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub1/module1.py
# 사용
sub.sub2.module2.mod2_test1()
#Module2 -> Test1
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub2/module2.py
sub.sub2.module2.mod2_test2()
#Module2 -> Test2
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub2/module2.py



 



# 예제2

from sub.sub1 import module1
from sub.sub2 import module2 as m2 # Alias(as) module2에게 m2라는 별명을 준 것.
# 사용
module1.mod1_test1()
#Module1 -> Test1
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub1/module1.py
module1.mod1_test2()
#Module1 -> Test2
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub1/module1.py
# 사용
m2.mod2_test1()
#Module2 -> Test1
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub2/module2.py
m2.mod2_test2()
#Module2 -> Test2
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub2/module2.py





# 예제3

from sub.sub1 import * # *는 전부 다 가져오겠다라는 뜻이다.
from sub.sub2 import *
# 사용
module1.mod1_test1()
#Module1 -> Test1
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub1/module1.py
module1.mod1_test2()
#Module1 -> Test2
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub1/module1.py
# 사용
module2.mod2_test1()
#Module2 -> Test1
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub2/module2.py
module2.mod2_test2()
#Module2 -> Test2
#Path: /Users/hong-gildong/Desktop/강의예제/예제 소스 파일/sub/sub2/module2.py

 

 

 

 

 

 

추가설명

 

 

TIL#28 import error 상대경로 절대경로

상대경로와 절대경로에서 어떤 경우에 import에러가 나타나는지 살펴보자. 상대경로: 내가 작업하는 위치를 기준으로 경로가 결정 절대경로: 최상단 디렉토리를 기준으로 하는 경로이다. 어느

higher77.tistory.com

 

 

 

TIL#36 하위,동일,상위파일 import하기

TIL#28 import error 상대경로 절대경로 상대경로와 절대경로에서 어떤 경우에 import에러가 나타나는지 살펴보자. import os print(os.path.abspath('.')) #현재 폴더의 절대경로를 물어보는 것 C:\Users\Jaesa..

higher77.tistory.com

 

'Python > Today I learned' 카테고리의 다른 글

TIL#29 예외(exception)  (0) 2021.05.19
TIL#28 import error 상대경로 절대경로  (0) 2021.05.18
TIL#26 모듈과 import, sys.path  (0) 2021.05.18
TIL#25 클래스 와 인스턴스(중요)  (0) 2021.05.18
TIL#24 input 사용법  (0) 2021.05.18

 

 

 

 

모듈

 

 

 

# 파이썬 모듈
Module : 함수, 변수, 클래스 등 파이썬 구성 요소 등을 모아놓은 파일

 

 


모듈(Module)개념

모듈이란?
모듈생성
sys.path실습
__name__설명
모듈 사용 실습

 

 

 

 


chapter06_02.py

def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y
def divide(x , y):
return x / y
def power(x, y):
return x ** y
# __name__ 사용
if __name__ == "__main__":
print('-' * 15)
print('called! __main__')
print(add(5,5))
print(subtract(15,5))
print(multiply(5,5))
print(divide(10,2))
print(power(5,3))
print('-' * 15)
---------------
called! __main__
10
10
25
5.0
125
---------------
#만약에 실행하는 위치가 다른 곳에서 import해서 호출할 때는 실행되지않고
#여기서 실행할 경우에는 실행이 된다.
#main은 실행되는 지점을 나타낸다.

 

 

 

 

 

module_test.py

# 모듈 사용 실습
import sys
print(sys) #built-in파이썬 내부적으로 쓰는 것이기에 이미 만들어진 것이다.
print(sys.path) #함수,모듈,패키지들이 등록이 되어있는 위치를 출력해줌
#파이썬 엔진이 여기있는 경로를 토대로 찾는다.
print(type(sys.path)) #리스트형태로 나오기 때문에 경로 삽입을 append로 해준다.
# 모듈 경로 삽입
# chapter06_02.py를 복사해서 test_module로 바꾼후 C드라이브 math에 넣어놨다.
sys.path.append('C:/math')
#sys.path.append는 영구적으로 등록되는게 아니다.
#영구적으로 등록하려면 윈도우나 맥에 환경 변수에 있는 파이썬 패스에 이 경로를 추가해줘야 한다.
print(sys.path) #경로 끝부분에 C:/math가 추가된다.
import test_module
# 모듈 사용
print(test_module.power(10, 3)) #1000
import chapter06_02
#chapter06_02.py모듈을 import해도 __name__ == __main__ 때문에 print문이 작동하지 않는다.

 

 

 

test_module.py

def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y
def divide(x , y):
return x / y
def power(x, y):
return x ** y

 

 

 

 

 

 

'Python > Today I learned' 카테고리의 다른 글

TIL#28 import error 상대경로 절대경로  (0) 2021.05.18
TIL#27 패키지와 import  (0) 2021.05.18
TIL#25 클래스 와 인스턴스(중요)  (0) 2021.05.18
TIL#24 input 사용법  (0) 2021.05.18
TIL#23 함수식 및 람다(lambda)  (0) 2021.05.15

 

 

 

클래스와 인스턴스

 

 

 

 

# 파이썬 클래스
# OOP(객체 지향 프로그래밍), Self, 인스턴스 메소드, 인스턴스 변수

# 클래스 and 인스턴스 차이 이해
네임스페이스 : 객체를 인스턴스화 할 때 저장된 공간
클래스 변수(속성) 직접 접근 가능, 공유
인스턴스 변수(속성) : 객체마다 별도 존재

 

 


##클래스 개념

oop란?(객체지향프로그램) : 생산성상향,재사용 극대화,유지보수,악영향 최소화,경제적
클래스(붕어빵 틀),인스턴스,
self개념
인스턴스 메소드
클래스,인스턴스 변수


 

 



# 예제1

class Dog: # Dog(object),Dog()라고 해도 된다. 모든 class는 object 상속받기 때문에 우리가 편한대로
# 하면 된다.
# 클래스 속성(변수)
species = 'firstdog'
# 초기화(__init__)/인스턴스(객체) 속성(변수)
# 모든 클래스는 초기화 메소드를 갖는다.
def __init__(self, name, age):
self.name = name
self.age = age

 

 

# __init__(생성자)

클래스로부터 인스턴스가 생성될 때 자동으로 실행되도록 약속되어 있는 메소드를 우리가 생성자라고 한다.

 

그말은, 인스턴스가 생성될 때 꼭 처리해야 되는 어떤 작업들을 __init__메소드의 내용으로 넣으면 실행된다는 것이다.

다시말해서 초기화를 할 수가 있는 것이다.

 

마치 우리가 컴퓨터를 처음 키면 부팅이라는 초기화를 하는 것처럼

자동차를 사용하러면 시동이라는 초기화를 하는 것처럼

 

우리는 객체를 만들 때 초기화 해야 되는 어떤 작업들을 __init__라고 하는 약속되어 있는 메소드의 본문에

넣어두는 것이다.

 

 

 

 

 


# 클래스 정보

print(Dog) #<class '__main__.Dog'>

 

 

 



# 인스턴스화

# 클래스를 가지고서 변수를 할당해서 메모리에 올라가고 id값을 갖는
# 실제로 설계도를 바탕으로 구현된 것을 인스턴스화 되었다고 한다.
# 사물인 보이는 것들 우리가 구현할 대상을 객체라고 한다.
a = Dog("mikky", 2)
b = Dog("baby", 3)
c = Dog("mikky", 2)
# 비교
print(a == b, id(a), id(b), id(c)) #False 1365738360784 1365738360688 1365738355056
#a,c는 값이 똑같지만 파이썬 코드 입장에서는 전혀 다른 객체로 간주하고 있다.
#인스턴스화 시킨 것들은 모두 다르다고 생각하면 된다.

 

 

 

 





네임스페이스(객체를 인스턴스화 할 때 저장된 공간/ 딕셔너리 형태)

print('dog1', a.__dict__) #dog1 {'name': 'mikky', 'age': 2}
print('dog2', b.__dict__) #dog2 {'name': 'baby', 'age': 3}

 

 

 

 



# 인스턴스 속성 확인

print('{} is {} and {} is {}'.format(a.name, a.age, b.name, b.age))
#mikky is 2 and baby is 3

 

 

 

 

 



# 클래스 속성 확인

if a.species == 'firstdog':
print('{0} is a {1}'.format(a.name, a.species))
#mikky is a firstdog
print(Dog.species) #firstdog 클래스로 직접접근 가능
print(a.species) #firstdog 인스턴스로도 직접접근 가능
print(b.species) #firstdog

 

 

 

 

 



# 예제2

# self의 이해

class SelfTest:
def func1(): #self가 없다는 것은 클래스 메소드라는 것이다.
print('Func1 called')
def func2(self): #self가 붙은 것은 인스턴스 메소드이다.
#self는 클래스 내부의 매개변수/ func2는 독립적인 공간에 있는 속성값에 접근하기 때문에
#공통메소드로써 사용할 수 있다.
print(id(self))
print('Func2 called')
# 클래스 안에 __init__매소드가 없으면 파이썬이 내부적으로 알아서 실행해준다.
# self라는 매개변수가 있으면 인스턴스화 시킨 변수가 self로 넘어간다.
f = SelfTest()
print(dir(f)) func1과 func2가 있다.
print(id(f)) #1365738354672
# f.func1() # 예외(에러) 매개변수가 없다.
f.func2() #1365738354672
#Func2 called
# self는 인스턴스를 요구한다. self에 f가 넘어간 것이다. f와 self의 아이디 값이 같다.
SelfTest.func1() #Func1 called self가 필요없이 클래스로 바로 접근해 호출할 수 있는 메소드
# SelfTest.func2() # 예외 인스턴스를 요구하지만 들어가지 않았기 때문에 에러
SelfTest.func2(f) #1365738354672 인스턴스를 넘겨주면 값이 나온다.
#Func2 called

 

<설명보충>

 

 

TIL#34 클래스 self

TIL#25 클래스 와 인스턴스(중요) 클래스와 인스턴스 # 파이썬 클래스 # OOP(객체 지향 프로그래밍), Self, 인스턴스 메소드, 인스턴스 변수 # 클래스 and 인스턴스 차이 이해 # 네임스페이

higher77.tistory.com

 

 

 



# 예제3
# 클래스 변수(공유), 인스턴스 변수(개별)

 

class Warehouse:
# 클래스 변수
stock_num = 0 # 재고
def __init__(self, name): #생성자
# 인스턴스 변수
self.name = name
Warehouse.stock_num += 1
def __del__(self): #소멸자 del메소드는 객체가 소멸할 때 자동으로 호출되는 함수다.
Warehouse.stock_num -= 1
user1 = Warehouse('Lee')
user2 = Warehouse('Cho')
print(Warehouse.stock_num) #2
print(user1.name) #Lee
print(user2.name) #Cho
print(user1.__dict__) #{'name': 'Lee'}
print(user2.__dict__) #{'name': 'Cho'}
print('before', Warehouse.__dict__) #before ···'stock_num': 2,···
print('>>>', user1.stock_num) #>>> 2
#Warehouse.__dict__에서는 stock_num이 2라고 나오는데 user1,2.__dict__에는 나오지 않지만
#user1.stock_num라고 치면 Warehouse클래스의 네임스페이스에 가서 알아서 찾아온다.
#어처피 모두 공유하기 때문에 user1,2.__dict__에 굳이 표시를 안해준 것이다.
del user1
print('after', Warehouse.__dict__) #after ···'stock_num': 1,···

 

 

 

 


# 예제4

class Dog2: # object 상속
# 클래스 속성
species = 'firstdog'
# 초기화/인스턴스 속성
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
return '{} is {} years old'.format(self.name, self.age)
def speak(self, sound):
return "{} says {}!".format(self.name, sound)
# 인스턴스 생성
c = Dog2('july', 4)
d = Dog2('Marry', 10)
# 메소드 호출
print(c.info())
print(d.info())
# 메소드 호출
print(c.speak('Wal Wal'))
print(d.speak('Mung Mung'))

 

 

 

 

 

'Python > Today I learned' 카테고리의 다른 글

TIL#27 패키지와 import  (0) 2021.05.18
TIL#26 모듈과 import, sys.path  (0) 2021.05.18
TIL#24 input 사용법  (0) 2021.05.18
TIL#23 함수식 및 람다(lambda)  (0) 2021.05.15
TIL#22 제어문 - 반복문(While문)  (0) 2021.05.15

+ Recent posts