or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdcore-processing.mddata-structures.mdexceptions.mdheic.mdindex.mdlogging.mdutilities.md

exceptions.mddocs/

0

# Error Handling

1

2

Exception classes for handling various error conditions during EXIF processing. These exceptions provide specific error types for different failure modes during metadata extraction.

3

4

## Capabilities

5

6

### Core EXIF Exceptions

7

8

Standard exceptions raised during EXIF processing for common error conditions.

9

10

```python { .api }

11

class InvalidExif(Exception):

12

"""

13

Raised when EXIF data is corrupted or invalid.

14

15

This exception indicates that the EXIF data structure does not conform

16

to the EXIF specification, such as:

17

- Corrupted IFD headers

18

- Invalid field types

19

- Malformed tag structures

20

- Inconsistent data lengths

21

22

The exception is raised during process_file() when strict=False mode

23

encounters unrecoverable data corruption.

24

"""

25

26

class ExifNotFound(Exception):

27

"""

28

Raised when no EXIF data is found in the image file.

29

30

This exception indicates that the image file does not contain EXIF

31

metadata or the metadata is not accessible, such as:

32

- Image formats without EXIF support

33

- Files with missing EXIF headers

34

- Corrupted file headers preventing EXIF location

35

- Unsupported EXIF variants

36

37

The exception is raised during format detection when no valid EXIF

38

data can be located in the file.

39

"""

40

```

41

42

### HEIC Format Exceptions

43

44

Specialized exceptions for HEIC/HEIF image format processing.

45

46

```python { .api }

47

class WrongBox(Exception):

48

"""

49

Raised when HEIC box structure is unexpected.

50

51

This exception occurs during HEIC file parsing when the ISO base

52

media file format box structure does not match expectations for

53

standard HEIC files.

54

"""

55

56

class NoParser(Exception):

57

"""

58

Raised when no parser is available for HEIC box type.

59

60

This exception occurs when encountering unsupported or unknown

61

box types in HEIC files that cannot be processed by the current

62

implementation.

63

"""

64

65

class BoxVersion(Exception):

66

"""

67

Raised when HEIC box version is unsupported.

68

69

This exception occurs when the version field in HEIC box headers

70

indicates a format version that is not supported by the parser.

71

"""

72

73

class BadSize(Exception):

74

"""

75

Raised when HEIC box size information is invalid.

76

77

This exception occurs when box size fields contain invalid or

78

inconsistent length information that would cause parsing errors

79

or file corruption.

80

"""

81

```

82

83

## Usage Examples

84

85

### Basic Exception Handling

86

87

```python

88

import exifread

89

90

def safe_extract_exif(filename):

91

"""Safely extract EXIF with proper error handling."""

92

try:

93

with open(filename, 'rb') as f:

94

tags = exifread.process_file(f)

95

return tags

96

except exifread.InvalidExif as e:

97

print(f"Invalid EXIF data in {filename}: {e}")

98

return None

99

except exifread.ExifNotFound as e:

100

print(f"No EXIF data found in {filename}: {e}")

101

return None

102

except IOError as e:

103

print(f"Cannot read file {filename}: {e}")

104

return None

105

106

# Usage

107

tags = safe_extract_exif('photo.jpg')

108

if tags:

109

print(f"Successfully extracted {len(tags)} EXIF tags")

110

else:

111

print("EXIF extraction failed")

112

```

113

114

### Strict Mode Exception Handling

115

116

```python

117

import exifread

118

119

def strict_exif_processing(filename):

120

"""Process EXIF in strict mode with detailed error handling."""

121

try:

122

with open(filename, 'rb') as f:

123

# Strict mode raises exceptions instead of ignoring errors

124

tags = exifread.process_file(f, strict=True)

125

return tags, None

126

except exifread.InvalidExif as e:

127

return None, f"Corrupted EXIF data: {e}"

128

except exifread.ExifNotFound as e:

129

return None, f"No EXIF metadata: {e}"

130

except ValueError as e:

131

# Strict mode may raise ValueError for invalid field types

132

return None, f"Invalid EXIF field: {e}"

133

except Exception as e:

134

return None, f"Unexpected error: {e}"

135

136

# Usage

137

tags, error = strict_exif_processing('photo.jpg')

138

if tags:

139

print("Strict processing successful")

140

else:

141

print(f"Processing failed: {error}")

142

```

143

144

### HEIC Exception Handling

145

146

```python

147

import exifread

148

from exifread.heic import WrongBox, NoParser, BoxVersion, BadSize

149

150

def process_heic_file(filename):

151

"""Process HEIC file with format-specific error handling."""

152

try:

153

with open(filename, 'rb') as f:

154

tags = exifread.process_file(f)

155

return tags, "success"

156

except WrongBox as e:

157

return None, f"HEIC box structure error: {e}"

158

except NoParser as e:

159

return None, f"Unsupported HEIC box type: {e}"

160

except BoxVersion as e:

161

return None, f"Unsupported HEIC version: {e}"

162

except BadSize as e:

163

return None, f"Invalid HEIC box size: {e}"

164

except exifread.ExifNotFound as e:

165

return None, f"No EXIF in HEIC file: {e}"

166

except Exception as e:

167

return None, f"General HEIC processing error: {e}"

168

169

# Usage for HEIC files

170

if filename.lower().endswith('.heic'):

171

tags, status = process_heic_file(filename)

172

if tags:

173

print(f"HEIC processing successful: {len(tags)} tags")

174

else:

175

print(f"HEIC processing failed: {status}")

176

```

177

178

### Batch Processing with Error Reporting

179

180

```python

181

import exifread

182

import os

183

from collections import defaultdict

184

185

def batch_process_with_errors(file_list):

186

"""Process multiple files and categorize errors."""

187

results = {

188

'success': [],

189

'no_exif': [],

190

'invalid_exif': [],

191

'file_errors': [],

192

'other_errors': []

193

}

194

195

error_counts = defaultdict(int)

196

197

for filename in file_list:

198

try:

199

with open(filename, 'rb') as f:

200

tags = exifread.process_file(f, strict=True)

201

results['success'].append((filename, len(tags)))

202

203

except exifread.ExifNotFound:

204

results['no_exif'].append(filename)

205

error_counts['no_exif'] += 1

206

207

except exifread.InvalidExif as e:

208

results['invalid_exif'].append((filename, str(e)))

209

error_counts['invalid_exif'] += 1

210

211

except IOError as e:

212

results['file_errors'].append((filename, str(e)))

213

error_counts['file_errors'] += 1

214

215

except Exception as e:

216

results['other_errors'].append((filename, str(e)))

217

error_counts['other_errors'] += 1

218

219

return results, error_counts

220

221

# Usage example

222

image_files = ['photo1.jpg', 'photo2.tiff', 'corrupted.jpg', 'no_exif.png']

223

results, error_counts = batch_process_with_errors(image_files)

224

225

print(f"Successfully processed: {len(results['success'])} files")

226

print(f"Files without EXIF: {error_counts['no_exif']}")

227

print(f"Files with invalid EXIF: {error_counts['invalid_exif']}")

228

print(f"File access errors: {error_counts['file_errors']}")

229

print(f"Other errors: {error_counts['other_errors']}")

230

```

231

232

### Logging Errors for Debugging

233

234

```python

235

import exifread

236

import logging

237

238

# Configure logging

239

logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')

240

logger = logging.getLogger(__name__)

241

242

def extract_exif_with_logging(filename):

243

"""Extract EXIF with comprehensive error logging."""

244

logger.info(f"Processing file: {filename}")

245

246

try:

247

with open(filename, 'rb') as f:

248

tags = exifread.process_file(f, debug=True)

249

logger.info(f"Successfully extracted {len(tags)} tags from {filename}")

250

return tags

251

252

except exifread.InvalidExif as e:

253

logger.error(f"Invalid EXIF in {filename}: {e}")

254

# Try non-strict mode as fallback

255

try:

256

with open(filename, 'rb') as f:

257

tags = exifread.process_file(f, strict=False)

258

logger.warning(f"Fallback processing recovered {len(tags)} tags")

259

return tags

260

except Exception as fallback_error:

261

logger.error(f"Fallback also failed: {fallback_error}")

262

return None

263

264

except exifread.ExifNotFound as e:

265

logger.warning(f"No EXIF data in {filename}: {e}")

266

return None

267

268

except Exception as e:

269

logger.error(f"Unexpected error processing {filename}: {e}")

270

return None

271

272

# Usage

273

tags = extract_exif_with_logging('problematic_photo.jpg')

274

```

275

276

### Custom Exception Handling

277

278

```python

279

import exifread

280

281

class ExifProcessingError(Exception):

282

"""Custom exception for EXIF processing workflows."""

283

def __init__(self, filename, original_error, error_type):

284

self.filename = filename

285

self.original_error = original_error

286

self.error_type = error_type

287

super().__init__(f"{error_type} in {filename}: {original_error}")

288

289

def safe_process_with_custom_exceptions(filename):

290

"""Process file with custom exception wrapping."""

291

try:

292

with open(filename, 'rb') as f:

293

return exifread.process_file(f)

294

except exifread.InvalidExif as e:

295

raise ExifProcessingError(filename, e, "INVALID_EXIF")

296

except exifread.ExifNotFound as e:

297

raise ExifProcessingError(filename, e, "NO_EXIF")

298

except IOError as e:

299

raise ExifProcessingError(filename, e, "FILE_ERROR")

300

301

# Usage with custom exception handling

302

try:

303

tags = safe_process_with_custom_exceptions('photo.jpg')

304

print("Processing successful")

305

except ExifProcessingError as e:

306

print(f"Processing failed: {e}")

307

print(f"Error type: {e.error_type}")

308

print(f"Filename: {e.filename}")

309

print(f"Original error: {e.original_error}")

310

```