Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python AttributeError: 'module' 객체에 'urlopen' 속성이 없는 오류 해결 방법

Python 3에서는 urllib 모듈의 request 함수에 접근하는 방식이 변경되었습니다. 따라서 Python 2 방식 그대로 "urlopen" 함수를 참조하려고 하면 "AttributeError: 'module' object has no attribute 'urlopen'" 오류가 발생합니다.

이 가이드에서는 해당 오류가 무엇을 의미하는지, 왜 발생하는지 살펴보고, 실제 예제를 통해 해결 방법까지 단계별로 알아보겠습니다.

AttributeError: 'module' object has no attribute 'urlopen'이란?

urllib 모듈은 URL을 열고 웹사이트에서 데이터를 읽어오는 다양한 기능을 제공합니다. 그런데 이 라이브러리의 사용 문법은 Python 2와 Python 3 사이에 큰 차이가 있습니다.

Python 2에서 "urlopen"은 urllib 모듈에 직접 포함되어 있어 urllib.urlopen 형태로 바로 호출할 수 있었습니다. 반면 Python 3에서는 "urlopen"이 urllib 패키지 내부의 "request" 모듈로 이동되었습니다.

  • Python 2: urllib → urlopen
  • Python 3: urllib → request → urlopen

"request" 모듈에는 urllib 패키지의 웹 요청 관련 함수들이 대부분 묶여 있습니다. AttributeError는 모듈에 존재하지 않는 속성에 접근하려 할 때 발생하는데, 이 경우 "urlopen"이 더 이상 urllib 모듈의 직접적인 속성이 아니기 때문에 오류가 발생하는 것입니다.

오류 발생 예시

JSONPlaceholder라는 테스트용 API 서비스에서 데이터를 가져오는 간단한 프로그램을 만들어 보겠습니다. 이 서비스는 개발 연습에 활용할 수 있는 더미 데이터를 무료로 제공합니다.

ID가 2번인 게시글 하나를 조회해 보겠습니다. 먼저 urllib 모듈을 임포트합니다:

import urllib

이 구문을 통해 프로그램 안에서 urllib 모듈의 함수들을 사용할 수 있습니다.

다음으로 "urlopen"을 사용해 요청을 보내 JSONPlaceholder API의 엔드포인트에서 데이터를 가져옵니다:

data = urllib.urlopen("https://jsonplaceholder.typicode.com/posts/2")
contents = data.read()
print(as_json)

이 코드는 JSONPlaceholder API에서 ID 2번 게시글의 데이터를 읽어온 뒤, print 문을 통해 요청에 대한 응답을 JSON 문자열 형식으로 콘솔에 출력합니다. 코드를 실행하면 어떻게 될까요?

Traceback (most recent call last):
  File "main.py", line 4, in <module>
	    data = urllib.urlopen("https://jsonplaceholder.typicode.com/posts/2")
AttributeError: module 'urllib' has no attribute 'urlopen'

프로그램이 오류를 반환하며 중단됩니다.

해결 방법

오류의 원인은 Python 2 문법으로 "urlopen" 메서드에 접근하고 있다는 점입니다. Python 3에서 "urlopen"은 urllib의 속성이 아니므로, urllib의 속성으로 참조하는 순간 프로그램이 정상적으로 실행되지 않습니다.

이 문제를 해결하려면 urllib 모듈에서 "request" 모듈을 함께 임포트해야 합니다. "urlopen" 메서드는 바로 이 모듈 안에 들어 있습니다:

import urllib.request

그다음, JSONPlaceholder API에서 데이터를 가져올 때 urllib.request 모듈을 참조하도록 코드를 수정합니다:

data = urllib.request.urlopen("https://jsonplaceholder.typicode.com/posts/2")
contents = data.read().decode('utf-8')

print(contents)

이 코드는 호출한 API 엔드포인트의 내용을 읽어옵니다. 수정된 코드를 실행해 보겠습니다:

{
  "userId": 1,
  "id": 2,
  "title": "qui est esse",
  "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
}

정상적으로 데이터가 출력되었습니다. 여기서 decode() 메서드를 사용해 응답을 디코딩했는데, 이렇게 하면 urlopen() 메서드가 반환하는 값을 사람이 읽을 수 있는 문자열 형태로 확인할 수 있습니다.

마무리

Python 3에서 "urlopen" 함수는 urllib 모듈의 직접적인 속성이 아닙니다. 이 함수를 사용하려면 코드에 urllib.request를 임포트한 후 urllib.request.urlopen() 형태로 호출해야 합니다.

이제 Python 2와 Python 3의 urllib 구조 차이만 기억하면, 이 오류를 전문가처럼 빠르게 해결할 수 있습니다!