How to Check Python Version in Scripts: Complete Guide
Learn how to check Python version programmatically using sys and platform modules. Discover methods to print, compare, and use version info in your scripts.
How can I print the version number of the current Python installation from my script? What are the different methods to check and display the Python version programmatically?
There are multiple ways to check and print the Python version from within your script, with the most common being using the sys module’s version_info attribute or the platform module. These methods allow you to retrieve detailed version information including major, minor, and micro version numbers for compatibility checking and conditional logic in your Python applications.
Contents
- How to Check Python Version in Scripts
- Using the sys Module for Version Information
- Using the platform Module for Version Details
- Comparing Python Versions Programmatically
- Practical Applications and Best Practices
- Sources
- Conclusion
How to Check Python Version in Scripts
When you need to print or check the Python version from within your script, Python provides several built-in methods that make this straightforward. The simplest and most common approach is to use the sys module, which gives you access to the version or version_info attributes containing detailed version information about the current Python interpreter.
Let’s start with the most basic method to print the Python version:
import sys
print(sys.version)
This code will output a string containing the Python version along with additional build information, typically looking something like this:
3.9.7 (default, Sep 10 2021, 14:59:43)
[GCC 11.2.0]
For a cleaner version number without build details, you might prefer:
import sys
print(sys.version.split()[0])
This will output just the version number: 3.9.7
Another approach is to use the platform module, which provides more detailed information about the Python implementation:
import platform
print(platform.python_version())
This will output a clean version string like 3.9.7.
The choice between these methods depends on your specific needs - whether you need the full version details with build information, a clean version number, or even more detailed implementation details.
Using the sys Module for Version Information
The sys module is part of Python’s standard library and provides access to system-specific parameters and functions, including version information. For checking the Python version programmatically, sys offers several attributes that can be useful.
sys.version
The sys.version attribute returns a string containing the Python version along with build information:
import sys
print(sys.version)
# Output: 3.9.7 (default, Sep 10 2021, 14:59:43) [MSC v.1916 64 bit (AMD64)]
This is useful when you need the complete version information including build details, which can be helpful for debugging or compatibility issues.
sys.version_info
For more structured access to version information, sys.version_info is particularly valuable. It returns a named tuple containing the version number as separate components:
import sys
print(sys.version_info)
# Output: sys.version_info(major=3, minor=9, micro=7, releaselevel='final', serial=0)
You can access each component individually:
import sys
version = sys.version_info
print(f"Python {version.major}.{version.minor}.{version.micro}")
print(f"Release level: {version.releaselevel}")
This is extremely useful when you need to implement version-specific logic in your code:
import sys
if sys.version_info >= (3, 6):
print("This feature requires Python 3.6 or higher")
# Use modern Python features
else:
print("Consider upgrading to Python 3.6+")
# Use compatible alternatives
sys.hexversion
For numerical comparisons, you can use sys.hexversion, which returns the version number as a single integer:
import sys
print(sys.hexversion)
# Output: 50928742 # This is 0x030907f0, representing Python 3.9.7
This is useful for numerical version comparisons without having to parse version strings manually.
Practical Examples with sys Module
Here’s how you might use these attributes in real-world scenarios:
import sys
def check_python_version():
"""Check and display Python version information"""
print(f"Python version: {sys.version}")
print(f"Version info: {sys.version_info}")
print(f"Major version: {sys.version_info.major}")
print(f"Full version as hex: {sys.hexversion}")
if sys.version_info >= (3, 8):
print("Using Python 3.8+ features")
elif sys.version_info >= (3, 6):
print("Using Python 3.6+ features")
else:
print("Python version may be outdated for some features")
check_python_version()
The sys module is particularly useful when you need to:
- Access version components individually
- Implement conditional logic based on version
- Compare versions numerically
- Log complete version information for debugging purposes
Using the platform Module for Version Details
The platform module provides another way to access Python version information, often with more detailed implementation-specific details. While sys gives you the core version information, platform can provide additional context about the Python installation.
platform.python_version()
This function returns a clean string with just the version number:
import platform
print(platform.python_version())
# Output: 3.9.7
platform.python_version_tuple()
For component-wise access, similar to sys.version_info:
import platform
print(platform.python_version_tuple())
# Output: ('3', '9', '7')
platform.python_implementation()
This function returns the implementation name, which is useful for distinguishing between standard CPython, Jython, IronPython, etc.:
import platform
print(platform.python_implementation())
# Output: CPython
platform.python_compiler()
This returns information about the compiler used to build the Python interpreter:
import platform
print(platform.python_compiler())
# Output: MSC v.1916 64 bit (AMD64)
platform.python_branch() and platform.python_revision()
These functions provide additional version details, particularly useful for development or debug builds:
import platform
print(f"Branch: {platform.python_branch()}")
print(f"Revision: {platform.python_revision()}")
Comprehensive Example with platform Module
Here’s how you might use the platform module to get a complete picture of your Python installation:
import platform
def print_python_system_info():
"""Print comprehensive Python system information"""
print("=== Python System Information ===")
print(f"Implementation: {platform.python_implementation()}")
print(f"Version: {platform.python_version()}")
print(f"Version tuple: {platform.python_version_tuple()}")
print(f"Compiler: {platform.python_compiler()}")
print(f"Build: {platform.python_build()}")
# Additional platform information
print(f"\nPlatform: {platform.platform()}")
print(f"Architecture: {platform.architecture()}")
print(f"Processor: {platform.processor()}")
print(f"Machine: {platform.machine()}")
print_python_system_info()
The platform module is particularly useful when you need:
- Implementation-specific information (CPython vs. others)
- Build and compiler details
- System context where Python is running
- A clean version string without extra information
Comparison: sys vs platform
While both modules provide version information, they serve slightly different purposes:
-
Use
syswhen you need: -
Simple version checking for conditional logic
-
Access to version components as integers
-
Numerical version comparisons
-
Minimal overhead for version checks
-
Use
platformwhen you need: -
Detailed implementation information
-
Clean version strings for display
-
System context information
-
Build and compiler details
Comparing Python Versions Programmatically
One of the most common reasons to check the Python version programmatically is to implement version-specific code paths. This is particularly important when:
- Using features that were introduced in specific Python versions
- Maintaining backward compatibility
- Providing alternative implementations for older Python versions
- Warning users about unsupported versions
Basic Version Comparisons
The most straightforward way to compare Python versions is using sys.version_info, which supports tuple comparisons:
import sys
if sys.version_info >= (3, 8):
# Use Python 3.8+ specific feature
print("Using walrus operator (:=)")
:= # This would cause syntax error in earlier versions
else:
# Use alternative for older Python
print("Not using walrus operator")
Semantic Versioning Comparisons
For more complex version comparisons, you might want to implement semantic versioning support:
import sys
from functools import total_ordering
@total_ordering
class Version:
def __init__(self, version_string):
self.version = tuple(map(int, version_string.split('.')))
def __eq__(self, other):
return self.version == other.version
def __lt__(self, other):
return self.version < other.version
def check_python_version_semantic():
current_version = Version(sys.version.split()[0])
required_version = Version("3.6")
if current_version >= required_version:
print(f"Python version {current_version} meets requirement {required_version}")
else:
print(f"Python version {current_version} does not meet requirement {required_version}")
check_python_version_semantic()
Handling Pre-release Versions
Python version strings might include pre-release indicators like a1, b2, or rc1. Here’s how to handle these:
import re
import sys
def parse_version(version_string):
"""Parse a version string into comparable components"""
match = re.match(r'^(\d+).(\d+).(\d+)([a-zA-Z]+)?(\d*)?$', version_string)
if not match:
raise ValueError(f"Invalid version string: {version_string}")
major, minor, micro, release, serial = match.groups()
return (
int(major),
int(minor),
int(micro),
release or 'final',
int(serial) if serial else 0
)
def compare_python_versions():
current_version = parse_version(sys.version.split()[0])
required_version = parse_version("3.9.0")
if current_version >= required_version:
print("Current Python version meets requirements")
else:
print("Consider upgrading Python version")
compare_python_versions()
Practical Examples of Version-Specific Code
Here are some real-world examples of how you might use version-specific code:
Example 1: Type Hints
import sys
def process_data(data):
if sys.version_info >= (3, 9):
# Using dict operator available in Python 3.9+
if isinstance(data, dict) and "value" in data:
return data["value"]
else:
# Alternative for Python < 3.9
if isinstance(data, dict) and "value" in data:
return data.get("value")
return None
Example 2: String Methods
import sys
def format_string(value):
if sys.version_info >= (3, 9):
# Using str.removeprefix available in Python 3.9+
return value.removeprefix("prefix_")
else:
# Alternative for Python < 3.9
prefix = "prefix_"
return value[len(prefix):] if value.startswith(prefix) else value
Example 3: Union Types
import sys
from typing import Union
def process_value(value: Union[str, int]) -> Union[str, int]:
if sys.version_info >= (3, 10):
# Using | operator for union types available in Python 3.10+
def process(val: str | int) -> str | int:
return val.upper() if isinstance(val, str) else val * 2
return process(value)
else:
# Alternative for Python < 3.10
def process(val: Union[str, int]) -> Union[str, int]:
return val.upper() if isinstance(val, str) else val * 2
return process(value)
Best Practices for Version Comparisons
When implementing version-specific code, consider these best practices:
- Check for minimum version rather than exact version:
# Good
if sys.version_info >= (3, 6):
# Use modern features
# Avoid
if sys.version_info == (3, 9, 7):
# This will fail on 3.9.8 or 3.10.0
- Use tuples for comparison:
# Good
if sys.version_info >= (3, 8, 5):
# Avoid
if sys.version_info >= "3.8.5": # Will cause TypeError
- Provide fallbacks for older versions:
try:
# Modern Python feature
result := some_function()
except SyntaxError:
# Fallback for older Python
result = some_function()
- Document version-specific behavior:
def advanced_feature():
"""
Provides advanced functionality.
Note: Requires Python 3.8+ for full functionality.
Limited feature set available for Python 3.6-3.7.
"""
if sys.version_info >= (3, 8):
# Full implementation
pass
else:
# Limited implementation
pass
Practical Applications and Best Practices
Now that we’ve explored the methods for checking Python version, let’s discuss practical applications and best practices for implementing version-aware code in your projects.
Common Use Cases for Version Checking
1. Compatibility Layers
When developing libraries or applications that need to work across multiple Python versions, version checking allows you to implement compatibility layers:
import sys
try:
# Python 3.9+ feature
from typing import Literal
except ImportError:
# Fallback for Python < 3.9
from typing_extensions import Literal
def process_status(status: Literal["active", "inactive", "pending"]):
# Version-agnostic implementation
pass
2. Feature Detection
Version checking helps detect which features are available:
import sys
# Check if positional-only parameters are supported
if sys.version_info >= (3, 8):
def process_data(data, /, *, strict=True):
"""Positional-only parameter available in Python 3.8+"""
pass
else:
def process_data(data, strict=True):
"""Alternative for Python < 3.8"""
pass
3. Deprecation Handling
When transitioning between versions, you can handle deprecation gracefully:
import sys
import warnings
def deprecated_function():
if sys.version_info >= (3, 10):
warnings.warn(
"This function is deprecated in Python 3.10+",
DeprecationWarning,
stacklevel=2
)
# Implementation
4. Environment Detection
Version checking helps detect the execution environment:
import sys
def detect_environment():
if sys.version_info >= (3, 9) and "PyPy" in sys.version:
return "pypy3.9+"
elif sys.version_info >= (3, 8):
return "cpython3.8+"
else:
return "older_python"
Best Practices for Version-Aware Code
1. Centralize Version Checks
Avoid scattering version checks throughout your code. Instead, centralize them:
# In a central utility module
import sys
PYTHON_VERSION = sys.version_info
IS_PYTHON_38_PLUS = PYTHON_VERSION >= (3, 8)
IS_PYTHON_39_PLUS = PYTHON_VERSION >= (3, 9)
IS_PYTHON_310_PLUS = PYTHON_VERSION >= (3, 10)
# In other modules
from .utils import IS_PYTHON_39_PLUS
def some_function():
if IS_PYTHON_39_PLUS:
# Use Python 3.9+ feature
pass
else:
# Fallback
pass
2. Use Feature Flags Instead of Version Checks
Consider using feature flags instead of direct version checks:
# configuration.py
FEATURE_NEW_PARSER = True # Set to False to disable
# parser.py
def parse_data(data):
if config.FEATURE_NEW_PARSER:
# Use new parser
pass
else:
# Use old parser
pass
This makes it easier to toggle features without changing code based on version.
3. Provide Graceful Degradation
Ensure your code degrades gracefully when features aren’t available:
import sys
try:
# Try to import a newer feature
from collections.abc import Mapping
except ImportError:
# Fallback for older Python versions
from collections import Mapping
def process_mapping(mapping):
if isinstance(mapping, Mapping):
# Process mapping
pass
4. Document Version Requirements
Clearly document version requirements for your code:
"""
This module provides advanced data processing capabilities.
Minimum Python version: 3.7
Full functionality requires Python 3.9+
"""
import sys
if sys.version_info < (3, 7):
raise RuntimeError("This module requires Python 3.7 or higher")
5. Use Version-Specific Imports
Take advantage of conditional imports for version-specific modules:
import sys
if sys.version_info >= (3, 9):
import zoneinfo
else:
import backports.zoneinfo as zoneinfo
def get_timezone():
return zoneinfo.ZoneInfo("America/New_York")
Real-World Examples
Example 1: Data Processing Library
import sys
from typing import Any, Dict, Optional, Union
class DataProcessor:
def __init__(self):
self._init_version_specific_features()
def _init_version_specific_features(self):
"""Initialize version-specific features"""
if sys.version_info >= (3, 9):
self.use_union_types = True
self.use_dict_union = True
else:
self.use_union_types = False
self.use_dict_union = False
def process_data(self, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
"""Process data with version-aware methods"""
if self.use_dict_union:
# Python 3.9+ dict type union
result: Dict[str, Any] | None = self._process_impl(data)
else:
# Python < 3.9 typing
result: Optional[Dict[str, Any]] = self._process_impl(data)
return result
def _process_impl(self, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
"""Actual implementation"""
if not data:
return None
if self.use_union_types:
# Python 3.10+ union operator
status: str | None = data.get("status")
else:
# Python < 3.10 typing
status: Optional[str] = data.get("status")
if status == "active":
return {"status": "processed", "data": data}
return None
Example 2: Configuration Manager
import sys
import json
from pathlib import Path
class ConfigManager:
def __init__(self, config_path: Path):
self.config_path = config_path
self._init_version_specific_features()
def _init_version_specific_features(self):
"""Initialize version-specific features"""
if sys.version_info >= (3, 10):
self.use_match_case = True
else:
self.use_match_case = False
def load_config(self) -> dict:
"""Load configuration file with version-aware parsing"""
try:
with open(self.config_path, 'r') as f:
if sys.version_info >= (3, 9):
# Use json module with improved error messages
return json.load(f)
else:
# Fallback for older Python
return json.load(f)
except FileNotFoundError:
return {}
def get_environment_config(self, env: str) -> dict:
"""Get configuration for specific environment"""
config = self.load_config()
if self.use_match_case:
# Python 3.10+ match-case statement
match env:
case "development":
return config.get("dev", {})
case "staging":
return config.get("staging", {})
case "production":
return config.get("prod", {})
case _:
return {}
else:
# Python < 3.10 if-else chain
if env == "development":
return config.get("dev", {})
elif env == "staging":
return config.get("staging", {})
elif env == "production":
return config.get("prod", {})
else:
return {}
Testing Version-Specific Code
When testing version-specific code, consider using testing tools that can simulate different Python versions:
import sys
from unittest.mock import patch
def test_version_specific_feature():
# Test with Python 3.9+
with patch.object(sys, 'version_info', (3, 9, 0)):
from mymodule import feature
assert feature() == "expected_result"
# Test with Python 3.7
with patch.object(sys, 'version_info', (3, 7, 0)):
from mymodule import feature
assert feature() == "fallback_result"
Future-Proofing Your Code
To make your code more resilient to future Python changes:
- Use version ranges rather than exact versions:
# Good
if sys.version_info >= (3, 7):
# Avoid
if sys.version_info == (3, 9, 7):
- Plan for deprecation:
import sys
import warnings
def deprecated_function():
if sys.version_info >= (3, 10):
warnings.warn(
"This function will be removed in Python 3.12",
DeprecationWarning,
stacklevel=2
)
# Implementation
- Document version transitions:
“”"
This function uses Python 3.9+ features.
It will be updated when Python 3.8 support is deprecated.
“”"
Sources
- Python sys Module Documentation — Official documentation for system-specific parameters and functions: https://docs.python.org/3/library/sys.html
- Python platform Module Documentation — Official documentation for accessing underlying platform data: https://docs.python.org/3/library/platform.html
- sys.version_info Practical Examples — Comprehensive guide to using sys.version_info for version checking: https://note.nkmk.me/en/python-sys-platform-version-info/
- How to Check Python Version from Command Line and in Script — Practical examples and formatting techniques: https://blog.finxter.com/check-python-version-from-command-line-and-in-script/
- How to Check the Python Version — Different output types and when to use each method: https://www.talentelgia.com/blog/how-to-check-the-python-version/
- Python Version Checking Best Practices — IT-focused perspective on version checking in automation scripts: https://syncromsp.com/blog/how-to-check-python-version/
Conclusion
Understanding how to check and display the Python version programmatically is essential for developing robust, cross-version compatible applications. The sys module provides direct access to version information through attributes like version, version_info, and hexversion, making it ideal for conditional logic and version comparisons. The platform module offers additional context about the Python implementation, including build details and system information.
When implementing version-aware code, it’s important to follow best practices like centralizing version checks, using feature flags instead of direct version comparisons when possible, and providing graceful degradation for older Python versions. These techniques ensure your code remains maintainable and adaptable as Python evolves.
Whether you’re building a library, an application, or a script, the ability to check the Python version programmatically allows you to leverage modern features while maintaining compatibility with older versions. By understanding these methods and applying them effectively, you can create code that works reliably across different Python environments.