Skip to main content

How to Resolve "ModuleNotFoundError: No module named 'urllib2'" Error in Python

When migrating older Python 2 code or running legacy scripts in a Python 3 environment, you will likely encounter the ModuleNotFoundError: No module named 'urllib2'. This error occurs because a significant reorganization of Python's standard library for handling URLs took place between Python 2 and Python 3. The urllib2 module, which was a staple for web requests in Python 2, does not exist in Python 3.

This guide will explain this change, show you how to fix the error by updating your code to use the modern urllib.request module, and provide methods for maintaining compatibility or automating the migration process.

Understanding the Error: The Renaming of urllib2 in Python 3

The ModuleNotFoundError is a direct consequence of the Python 2 to Python 3 transition. In Python 2, URL handling functionality was split across several modules, including urllib, urllib2, and urlparse. This was often confusing for developers.

In Python 3, these modules were consolidated and refactored into a single urllib package with several submodules:

  • urllib2 was largely replaced by urllib.request and urllib.error.
  • urllib was largely replaced by urllib.request, urllib.parse, and urllib.error.
  • urlparse was moved to urllib.parse.

Therefore, when Python 3 encounters import urllib2, it cannot find the module and raises the ModuleNotFoundError.

Reproducing the ModuleNotFoundError

The following code, which was valid in Python 2, will reliably trigger the error when executed with a Python 3 interpreter.

Example of the code causing the error:

# This code is written for Python 2
from urllib2 import urlopen

try:
response = urlopen("https://www.python.org")
print("Request successful.")
except NameError as e:
print(f"urlopen is not defined because of the import error: {e}")
except Exception as e:
# This block will be hit first due to the ModuleNotFoundError
print(f"An unexpected error occurred: {e}")

Output when run with python3:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'urllib2'

The standard and most direct way to fix this error for modern Python 3 code is to change the import statement to use the urllib.request submodule.

Solution:

# This is the correct way for Python 3
from urllib.request import urlopen

response = urlopen("https://www.python.org")
print(f"Request successful, status code: {response.getcode()}")
print(f"First 100 bytes of response: {response.read(100)}")

Output:

Request successful, status code: 200
First 100 bytes of response: b'<!doctype html>\n<!--[if lt IE 7]><html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9"><![endif]-->\n<!--[if IE'
note

For a complete list of functions and classes available, you can refer to the official urllib.request documentation.

Solution 2: Use a try-except Block for Python 2 & 3 Compatibility

If you are writing a library or application that needs to support both Python 2 and Python 3, you can use a try-except block to handle the different import paths gracefully.

The Compatibility Solution:

try:
# For Python 3
from urllib.request import urlopen
except ImportError:
# Fallback for Python 2
from urllib2 import urlopen

# The rest of your code can now use urlopen regardless of the Python version
response = urlopen("https://www.python.org")
print(f"Request successful, status code: {response.getcode()}")

Output (in either Python 2 or 3):

Request successful, status code: 200
note

This pattern attempts the Python 3 import first and, if it fails with an ImportError (indicating a Python 2 environment), it falls back to the legacy urllib2 import.

Solution 3: Use the 2to3 Tool for Automatic Code Migration

If you are migrating a larger Python 2 codebase, manually changing every import statement can be tedious. Python provides a command-line tool called 2to3 that automatically converts Python 2 code to Python 3 syntax, including fixing urllib2 imports.

The Automatic Conversion Solution: Suppose you have a file named script.py with Python 2 code.

# This command will show the proposed changes without modifying the file
2to3 script.py

# Use the -w flag to write the changes directly to the file
# This will create a backup of the original file named script.py.bak
2to3 -w script.py

Running this tool will automatically transform lines like from urllib2 import urlopen into from urllib.request import urlopen.

warning

While 2to3 is a powerful tool, it's not infallible. Always review the changes it makes with a tool like diff and test your code thoroughly after the conversion.

Conclusion

The ModuleNotFoundError: No module named 'urllib2' is a clear indicator that you are running Python 2 code in a Python 3 environment. To resolve it:

  1. For modern Python 3 code, the best practice is to manually update your imports from urllib2 to the appropriate urllib submodule, typically urllib.request.
  2. For code that must support both versions, use a try-except ImportError block to create a compatibility layer.
  3. For migrating entire projects, the 2to3 command-line tool can automate the conversion process, saving significant time and effort.

By understanding this fundamental change between Python 2 and 3, you can easily update your code to work correctly in modern Python environments.