Python wrapper around the solc Solidity compiler
—
Comprehensive error handling for compilation failures and system issues. The py-solc library provides structured exceptions that give detailed information about what went wrong during compilation or installation.
Base exception class for all solc-related errors.
class SolcError(Exception):
"""
Base exception for solc compilation errors.
Attributes:
command (list): Command that failed
return_code (int): Process return code
stdin_data (str): Input data sent to process (or None)
stdout_data (str): Process stdout output (or None)
stderr_data (str): Process stderr output (or None)
message (str): Error message
"""
def __init__(self, command, return_code, stdin_data, stdout_data, stderr_data, message=None):
"""
Initialize SolcError with process information.
Args:
command (list): The solc command that was executed
return_code (int): Process exit code
stdin_data: Data sent to stdin (converted to string)
stdout_data: Process stdout (converted to string)
stderr_data: Process stderr (converted to string)
message (str): Custom error message (optional)
"""Specific exception raised when no contracts are found during compilation.
class ContractsNotFound(SolcError):
"""
Raised when no contracts are found during compilation.
This exception inherits all attributes from SolcError.
Default message: "No contracts found during compilation"
"""from solc import compile_source, SolcError
try:
result = compile_source('''
pragma solidity ^0.4.24;
contract BrokenContract {
// Syntax error: missing semicolon
uint256 value = 42
}
''')
except SolcError as e:
print(f"Compilation failed: {e}")
print(f"Command: {' '.join(e.command)}")
print(f"Return code: {e.return_code}")
if e.stderr_data:
print(f"Error output: {e.stderr_data}")from solc import compile_source, ContractsNotFound
try:
# Source with no contracts (just comments)
result = compile_source('''
pragma solidity ^0.4.24;
// This file contains no contracts
''')
except ContractsNotFound as e:
print("No contracts found in the source code")
print(f"Source code processed: {e.stdin_data[:100]}...")
# Allow empty compilation instead
result = compile_source('''
pragma solidity ^0.4.24;
// This file contains no contracts
''', allow_empty=True)
print(f"Empty compilation result: {result}")from solc import compile_standard, SolcError, ContractsNotFound
def safe_compile(source_code):
try:
return compile_standard({
'language': 'Solidity',
'sources': {
'contract.sol': {'content': source_code}
},
'settings': {
'outputSelection': {
'*': {'*': ['abi', 'evm.bytecode']}
}
}
})
except ContractsNotFound as e:
print("Warning: No contracts found in source")
return None
except SolcError as e:
if e.return_code == 1:
print("Compilation error (syntax/semantic issues)")
elif e.return_code == 2:
print("Solc internal error")
else:
print(f"Unknown solc error (code {e.return_code})")
# Try to extract detailed error information
if e.stdout_data:
try:
import json
output = json.loads(e.stdout_data)
if 'errors' in output:
for error in output['errors']:
print(f" {error.get('severity', 'error')}: {error.get('message', 'Unknown error')}")
except (json.JSONDecodeError, KeyError):
print(f"Raw error output: {e.stderr_data}")
return Nonefrom solc import install_solc
def safe_install(version, platform=None):
try:
install_solc(version, platform=platform)
print(f"Successfully installed solc {version}")
except ValueError as e:
print(f"Invalid version or platform: {e}")
except OSError as e:
print(f"System error during installation: {e}")
# Check common issues
if "git" in str(e).lower():
print("Make sure git is installed and available in PATH")
elif "permission" in str(e).lower():
print("Permission denied - check write access to ~/.py-solc/")
elif "network" in str(e).lower() or "download" in str(e).lower():
print("Network error - check internet connection")
except Exception as e:
print(f"Unexpected error: {e}")
print("Please check system requirements and try again")from solc import compile_source, SolcError, ContractsNotFound
def analyze_compilation_error(source_code):
try:
result = compile_source(source_code)
return result
except ContractsNotFound as e:
return {
'success': False,
'error_type': 'no_contracts',
'message': 'No contracts found in source code',
'suggestion': 'Make sure your source code defines at least one contract'
}
except SolcError as e:
error_info = {
'success': False,
'error_type': 'compilation_error',
'return_code': e.return_code,
'command': e.command,
'message': str(e)
}
# Analyze stderr for common issues
if e.stderr_data:
stderr_lower = e.stderr_data.lower()
if 'parsererror' in stderr_lower:
error_info['category'] = 'syntax_error'
error_info['suggestion'] = 'Check for syntax errors like missing semicolons, brackets, etc.'
elif 'typeerror' in stderr_lower:
error_info['category'] = 'type_error'
error_info['suggestion'] = 'Check variable types and function signatures'
elif 'declarationerror' in stderr_lower:
error_info['category'] = 'declaration_error'
error_info['suggestion'] = 'Check for undeclared variables or duplicate declarations'
elif 'not found' in stderr_lower:
error_info['category'] = 'import_error'
error_info['suggestion'] = 'Check file paths and import statements'
else:
error_info['category'] = 'unknown_compilation_error'
error_info['suggestion'] = 'Review the full error message for details'
return error_info
# Usage
result = analyze_compilation_error('''
pragma solidity ^0.4.24;
contract Test {
uint256 value = ; // Syntax error
}
''')
if not result['success']:
print(f"Error: {result['message']}")
print(f"Suggestion: {result['suggestion']}")from solc import compile_source, SolcError
try:
compile_source("invalid solidity code")
except SolcError as e:
print("Exception Details:")
print(f" Message: {e.message}")
print(f" Command: {' '.join(e.command) if e.command else 'None'}")
print(f" Return Code: {e.return_code}")
print(f" Has stdin data: {e.stdin_data is not None}")
print(f" Has stdout data: {e.stdout_data is not None}")
print(f" Has stderr data: {e.stderr_data is not None}")
if e.stdin_data:
print(f" Input (first 100 chars): {e.stdin_data[:100]}...")
if e.stdout_data:
print(f" Stdout (first 200 chars): {e.stdout_data[:200]}...")
if e.stderr_data:
print(f" Stderr: {e.stderr_data}")These occur when solc itself fails to compile the Solidity code:
These occur when compilation succeeds but no contracts are found:
These occur due to system-level issues:
try:
result = compile_source(source)
except ContractsNotFound:
# Handle specifically
pass
except SolcError:
# Handle compilation errors
pass
except Exception:
# Handle unexpected errors
passtry:
result = compile_source(source)
except SolcError as e:
user_message = f"Failed to compile Solidity code: {e.message}"
if "ParserError" in str(e):
user_message += "\nPlease check your syntax for missing semicolons or brackets."
raise RuntimeError(user_message) from eimport logging
try:
result = compile_source(source)
except SolcError as e:
logging.error(f"Solc compilation failed:")
logging.error(f" Command: {' '.join(e.command)}")
logging.error(f" Return code: {e.return_code}")
logging.error(f" Stderr: {e.stderr_data}")
raisedef try_compile_with_fallback(source):
try:
return compile_source(source)
except ContractsNotFound:
# Try with allow_empty
return compile_source(source, allow_empty=True)
except SolcError as e:
if "version" in str(e).lower():
# Try without pragma version
source_no_pragma = re.sub(r'pragma solidity[^;]*;', '', source)
return compile_source(source_no_pragma)
raiseInstall with Tessl CLI
npx tessl i tessl/pypi-py-solc