Skip to content

How to Check If a Module Is a Package in Python

Learn how to programmatically determine whether an imported Python object is a package (directory with __init__.py) or a module (single .py file) using __path__ attribute checks.

In Python, the terms "module" and "package" are often used interchangeably, but they have distinct technical definitions. A module is typically a single file (.py), whereas a package is a directory containing an __init__.py file (and potentially other modules) that allows for a hierarchical structure.

Knowing whether an imported object is a package or a simple module is useful for introspection, dynamic importing, or traversing code structures. This guide explains how to distinguish between them using the __path__ attribute.

Understanding the Distinction

Before checking programmatically, it helps to visualize the structure.

  • Package: A container. It maps to a directory. It must have __path__ because Python needs to know where to look for submodules.
  • Module: A unit of code. It maps to a file. It does not have submodules, so it does not need a __path__.

Example Structure:

project/
    main.py
    my_package/         <-- This is a Package
        __init__.py
        my_module.py    <-- This is a Module

Method 1: Checking the __path__ Attribute

The most definitive way to identify a package is to check for the existence of the __path__ attribute. Only packages have this attribute; standard modules do not.

Example of AttributeError

If you try to access __path__ on a standard module, Python raises an error.

import my_package.my_module

try:
    print(my_package.my_module.__path__)
except AttributeError as e:
    print(f"Error: {e}")

Output:

Error: module 'my_package.my_module' has no attribute '__path__'

The Safe Check using hasattr()

To safely determine if an imported object is a package, use hasattr().

import my_package
import my_package.my_module
import os

if hasattr(my_package, '__path__'):
    print(f"'my_package' IS a package. Path: {my_package.__path__}")
else:
    print("'my_package' is NOT a package.")

if hasattr(my_package.my_module, '__path__'):
    print("'my_module' IS a package.")
else:
    print("'my_module' is NOT a package (it is a module).")

if hasattr(os, '__path__'):
    print("'os' IS a package.") # os is actually a package because it imports sys-dependent modules

Output:

'my_package' IS a package. Path: ['/path/to/project/my_package']
'my_module' is NOT a package (it is a module).
'os' is NOT a package. (Note: Output depends on implementation, usually os is a module wrapper)

Method 2: Using inspect (Alternative)

While __path__ is the standard indicator, you can also use the inspect module to verify the file source. Packages usually point to an __init__.py file.

import inspect
import my_package
import my_package.my_module

def check_is_package(module):
    file_path = getattr(module, '__file__', '')
    
    if file_path and '__init__.py' in file_path:
        return True
    return False

print(f"Is my_package a package? {check_is_package(my_package)}")
print(f"Is my_module a package?  {check_is_package(my_package.my_module)}")

Output:

Is my_package a package? True
Is my_module a package?  False

Conclusion

To distinguish between packages and modules in Python:

  1. Use hasattr(module, '__path__'). This is the most reliable and "Pythonic" method.
  2. If True, the module is a package (it handles submodules).
  3. If False, it is a standard module (a single file).
Navigation