파이참에서 모듈을 설치하고 그 모듈을 import 해서 사용할 때

ModuleNotFoundError

이렇게 ModuleNotFoundError가 나는 경우가 있다.

 

분명히 이렇게 pip로 성공적으로 설치했는데 말이다.

이럴 때 간단하게 파이참에서 해결할 수 있다.

 

1. Settings에 들어간다.

Settings 클릭

 

2. + 를 누른다.

 

3. 원하는 모듈의 이름을 검색한다.

 

4. 원하는 모듈을 선택하고 Install Package를 누른다.

 

5. 설치중

 

6. 설치완료

 

 

아까는 빨간줄로 에러가 났던 것이 이제 에러 안 남

아까는 빨간 줄이 그어지면서 에러가 났던 모듈 import 부분이 에러가 안 나고 프로그램이 멀쩡히 잘 돌아간다.

'Python' 카테고리의 다른 글

[Python] 백준 시간초과 해결, 입출력 속도 개선  (3) 2020.02.01

입력을 받을 때에는

n = int(input())

보다는

from sys import stdin
n = int(stdin.readline())

이 코드가 더 빠르다. 한 줄에 입력 개수가 한 개일지라도 input()보다는 sys.stdin.readline()이 더 빠르다.

 

입력받아야 할 것이 한 줄에 여러 개라면 input()보다 readline() 함수를 이용하는 것이 훨씬 더 빠르다.

li = list(map(int, stdin.readline().split()))

readline() 함수 뒤에 split() 함수를 연이어서 호출하면 아예 이렇게 list로 받는 것이 가능하다.

게다가 문자열이 아니라 아예 int로 바꿔서까지 저장할 수 있으니 정말 편리하다.

 

입력이 만약에 이렇게 들어온다면?

3 3
1 1 0
1 1 1
1 0 1
1 1 1

이 코드로 입력받을 수 있다.

n, m = list(map(int, stdin.readline().split()))
li = []
for i in range(n):
    li.append(list(map(int, stdin.readline().split())))

대입 연산자의 우측에 list가 있고 대입연산자의 좌측에 list의 크기 만큼 개수의 변수가 있으면 변수 각각에 list의 원소가 저장된다. n, m 이렇게 두 개를 받을 때에도 readline().split()을 쓰면 유용하다.

사실 이 정도 두 개 변수 받을 때 input() 대신 readline()을 쓴다고 시간초과 문제가 해결되는 것은 아니고

속도 향상의 핵심은 저 for문이다.

저 for문을 수행하고 나면 이차원 list(이차원 배열)가 만들어진다.

 

만약에 저 for문을

for i in range(n):
	for j in range(m):
    		li.append(int(input()))

이렇게 이중 for문을 사용해서 input() 함수를 통해 입력받는다면 속도는 훨씬 느려진다. for문 자체도 이중이기 때문에 겉보기로만 대충 구한 시간복잡도이지만 시간복잡도가 O(n)에서 O(n^2)로 훨씬 커졌고 함수 자체도 readline() 함수보다 input() 함수가 더 느리다. 따라서 이 코드는 위의 코드보다 훨씬 느리다.

 

만약 위와 같이 한 줄에 여러 데이터를 공백을 구분하는게 아니라

5
5
4
3
2
1

이렇게 한 줄에 한 개의 데이터만 주어진다면?

 

앞의 코드에서는 append() 함수를 이용해서 빈 리스트에 입력받은 값을 저장해줬다.

하지만 이 경우 리스트를 먼저 초기화해주고 인덱스를 이용해서 접근해서 값을 저장하면 속도가 조금 더 개선된다.

li = [0] * n
for i in range(n):
	li[i] = int(sys.stdin.readline())

이렇게 li[i]로 접근해서 값을 저장한다면

 

li = []
for i in range(n):
	li.append(int(sys.stdin.readline()))

이렇게 빈 리스트에 append() 함수를 이용해 값을 저장하는 것보다 조금 더 빨라진다.

 

 

백준 온라인 저지 사이트에

리스트를 초기화해놓고 인덱스로 접근하는 이 코드로 제출하면

n = int(input())
li = [0] * n
from sys import stdin
for i in range(n):
    li[i] = int(stdin.readline())

s = ""
li.sort()
for i in li:
    s += (str(i) + '\n')
print(s)

1468ms가 걸리지만

append() 함수로 데이터를 덧붙이는 식으로 하면

n = int(input())
li = []
from sys import stdin
for i in range(n):
    li.append(int(stdin.readline()))

s = ""
li.sort()
for i in li:
    s += (str(i) + '\n')
print(s)

1592ms가 걸리는 것을 볼 수 있다.

 

그리고 출력할 때에 줄바꿈을 해야 한다면

for i in li:
	print(i)

이렇게 하는 것은 매우 비효율적이고

 

s = ""
for i in li:
    s += (str(i) + '\n')
print(s)

이렇게 s라는 string 변수에 줄바꿈 문자까지 합친 문자열을 계속 계속 덧붙여서 저장하고 나중에 한번에 s를 출력하는 것이 더 빠르다.

 

실제로 백준 온라인 저지 사이트에서 돌려보았다.

n = int(input())
li = [0] * n
from sys import stdin
for i in range(n):
    li[i] = int(stdin.readline())

li.sort()
for i in li:
    print(i)

이 코드를 제출하면

1708ms가 걸리지만

출력 부분만 바꿔서

n = int(input())
li = [0] * n
from sys import stdin
for i in range(n):
    li[i] = int(stdin.readline())

s = ""
li.sort()
for i in li:
    s += (str(i) + '\n')
print(s)

이렇게 돌리면

1468ms가 걸리는 것을 볼 수 있다.

 

그리고 여기에서 또 한 번 느끼는 것은 메모리 양과 수행시간은 반비례 한다는 것이다.

역시 하나를 얻으려면 하나를 포기해야 한다는 것은 세상 만물의 진리인 것 같다.

메모리 사용량을 줄이려고 s라는 변수를 안 쓰고 print 하면 메모리는 덜 쓸 수 있지만 시간이 오래 걸리고

시간을 줄이려고 s라는 문자열 변수를 만들어서 출력하면 메모리는 조금 더 쓰지만 시간을 줄일 수 있다.

 

정리하자면

1. input()보다는 sys.readline()을 쓰자.

2. 빈 리스트에 append()로 추가하는 것보단 입력 받을 개수 만큼 초기화된 리스트에 인덱스를 이용해서 접근해서 그 위치에 직접 입력받자.

3. 줄바꿈 할때엔 print()가 아니라 '\n', for문 마다 출력하지 말고 문자열 변수에 저장해놓고 한 번에 출력하자.

+ Recent posts