0
# File Operations
1
2
The XMPFiles class provides convenient access to XMP metadata in files with smart handlers for various file formats. It manages file opening, XMP extraction, modification, and writing back to files.
3
4
## Capabilities
5
6
### XMPFiles Class
7
8
API for accessing main metadata in files with smart file handlers.
9
10
```python { .api }
11
class XMPFiles:
12
def __init__(self, **kwargs):
13
"""
14
Create XMPFiles instance.
15
16
Parameters:
17
- file_path (optional): str, path to file to open
18
"""
19
```
20
21
### File Operations
22
23
```python { .api }
24
def open_file(self, file_path, **kwargs):
25
"""
26
Open file and read XMP metadata.
27
28
Parameters:
29
- file_path: str, path to file
30
- **kwargs: optional keyword arguments from XMP_OPEN_OPTIONS
31
32
Raises:
33
XMPError: if file already open or operation fails
34
"""
35
36
def close_file(self, close_flags=0):
37
"""
38
Close file and write XMP changes.
39
40
Parameters:
41
- close_flags: int, optional close flags from XMP_CLOSE_OPTIONS
42
(default: XMP_CLOSE_NOOPTION)
43
"""
44
```
45
46
### Metadata Access
47
48
```python { .api }
49
def get_xmp(self):
50
"""
51
Get XMP metadata from file.
52
53
Returns:
54
XMPMeta: New XMPMeta instance with file's XMP data, or None if no XMP
55
56
Raises:
57
XMPError: on failure
58
"""
59
60
def put_xmp(self, xmp_obj):
61
"""
62
Write XMP metadata to file.
63
64
Parameters:
65
- xmp_obj: XMPMeta instance with XMP data to write
66
67
Raises:
68
XMPError: on failure
69
"""
70
71
def can_put_xmp(self, xmp_obj):
72
"""
73
Check if XMP can be written to file.
74
75
Parameters:
76
- xmp_obj: XMPMeta instance
77
78
Returns:
79
bool: True if XMP can be written to file
80
"""
81
```
82
83
## File Format Support
84
85
The XMPFiles class includes smart handlers for various file formats:
86
87
- **Image formats**: JPEG, TIFF, PNG, GIF, WebP
88
- **Document formats**: PDF, PostScript, EPS
89
- **RAW formats**: Camera RAW files (via Adobe Camera Raw)
90
- **Video formats**: Various multimedia formats
91
- **Generic**: Packet scanning fallback for unknown formats
92
93
## Open Options
94
95
Available options for `open_file()` method from `libxmp.consts`:
96
97
```python { .api }
98
XMP_OPEN_NOOPTION = 0x00000000 # No special options
99
XMP_OPEN_READ = 0x00000001 # Open for read-only access
100
XMP_OPEN_FORUPDATE = 0x00000002 # Open for read-write access
101
XMP_OPEN_ONLYXMP = 0x00000004 # Only process XMP, ignore other metadata
102
XMP_OPEN_CACHETNAIL = 0x00000008 # Cache thumbnail if present
103
XMP_OPEN_STRICTLY = 0x00000010 # Strict conformance checking
104
XMP_OPEN_USESMARTHANDLER = 0x00000020 # Use smart handlers
105
XMP_OPEN_USEPACKETSCANNING = 0x00000040 # Use packet scanning fallback
106
XMP_OPEN_LIMITSCANNING = 0x00000080 # Limit packet scanning
107
XMP_OPEN_INBACKGROUND = 0x10000000 # Set if calling from background thread
108
```
109
110
## Close Options
111
112
Available options for `close_file()` method:
113
114
```python { .api }
115
XMP_CLOSE_NOOPTION = 0x0000 # No special options
116
XMP_CLOSE_SAFEUPDATE = 0x0001 # Write XMP into safe temp file first
117
```
118
119
## Usage Examples
120
121
### Basic File Operations
122
123
```python
124
from libxmp import XMPFiles, XMPMeta, XMPError
125
126
# Open file and read XMP
127
try:
128
xmpfile = XMPFiles(file_path="photo.jpg")
129
xmp_data = xmpfile.get_xmp()
130
131
if xmp_data:
132
# Read existing metadata
133
creator = xmp_data.get_property("http://purl.org/dc/elements/1.1/", "creator")
134
print(f"Original creator: {creator}")
135
136
# Modify metadata
137
xmp_data.set_property("http://purl.org/dc/elements/1.1/", "creator", "Updated Creator")
138
xmp_data.set_property("http://ns.adobe.com/xap/1.0/", "CreatorTool", "Python XMP Toolkit")
139
140
# Write back to file
141
xmpfile.put_xmp(xmp_data)
142
else:
143
print("No XMP metadata found in file")
144
145
# Close file (writes changes)
146
xmpfile.close_file()
147
148
except XMPError as e:
149
print(f"XMP error: {e}")
150
```
151
152
### Working with Different File Types
153
154
```python
155
from libxmp import XMPFiles, XMPMeta
156
from libxmp.consts import XMP_OPEN_FORUPDATE, XMP_CLOSE_SAFEUPDATE
157
158
# Process multiple file types
159
file_paths = ["document.pdf", "image.tiff", "photo.jpg"]
160
161
for file_path in file_paths:
162
try:
163
# Open with specific options
164
xmpfile = XMPFiles()
165
xmpfile.open_file(file_path, open_forupdate=True)
166
167
xmp_data = xmpfile.get_xmp()
168
if not xmp_data:
169
# Create new XMP if none exists
170
xmp_data = XMPMeta()
171
172
# Add processing timestamp
173
from datetime import datetime
174
xmp_data.set_property_datetime(
175
"http://ns.adobe.com/xap/1.0/",
176
"ModifyDate",
177
datetime.now()
178
)
179
180
# Check if we can write XMP to this file type
181
if xmpfile.can_put_xmp(xmp_data):
182
xmpfile.put_xmp(xmp_data)
183
print(f"Updated XMP in {file_path}")
184
else:
185
print(f"Cannot write XMP to {file_path}")
186
187
# Close with safe update
188
xmpfile.close_file(close_flags=XMP_CLOSE_SAFEUPDATE)
189
190
except Exception as e:
191
print(f"Error processing {file_path}: {e}")
192
```
193
194
### Advanced File Handling
195
196
```python
197
from libxmp import XMPFiles, XMPMeta
198
from libxmp.consts import *
199
200
def process_file_metadata(file_path, metadata_updates):
201
"""
202
Process file metadata with comprehensive error handling.
203
204
Args:
205
file_path: Path to file
206
metadata_updates: Dict of namespace -> {property: value} mappings
207
"""
208
xmpfile = None
209
try:
210
# Open file with comprehensive options
211
xmpfile = XMPFiles()
212
xmpfile.open_file(
213
file_path,
214
open_forupdate=True,
215
open_usesmarthandler=True,
216
open_usepacketscanning=True
217
)
218
219
# Get existing XMP or create new
220
xmp_data = xmpfile.get_xmp()
221
if not xmp_data:
222
xmp_data = XMPMeta()
223
224
# Apply metadata updates
225
for namespace, properties in metadata_updates.items():
226
for prop_name, prop_value in properties.items():
227
if isinstance(prop_value, list):
228
# Handle arrays
229
for item in prop_value:
230
xmp_data.append_array_item(namespace, prop_name, item)
231
else:
232
# Handle simple properties
233
xmp_data.set_property(namespace, prop_name, prop_value)
234
235
# Verify we can write before attempting
236
if xmpfile.can_put_xmp(xmp_data):
237
xmpfile.put_xmp(xmp_data)
238
return True
239
else:
240
print(f"Cannot write XMP to {file_path}")
241
return False
242
243
except Exception as e:
244
print(f"Error processing {file_path}: {e}")
245
return False
246
247
finally:
248
if xmpfile:
249
try:
250
xmpfile.close_file(close_flags=XMP_CLOSE_SAFEUPDATE)
251
except:
252
pass # Ignore close errors after main operation failure
253
254
# Usage
255
updates = {
256
"http://purl.org/dc/elements/1.1/": {
257
"creator": "John Doe",
258
"subject": ["photography", "landscape", "nature"]
259
},
260
"http://ns.adobe.com/xap/1.0/": {
261
"CreatorTool": "Python XMP Toolkit"
262
}
263
}
264
265
success = process_file_metadata("photo.jpg", updates)
266
if success:
267
print("Metadata updated successfully")
268
```
269
270
## Error Handling
271
272
Common XMP file operation errors and handling:
273
274
```python
275
from libxmp import XMPFiles, XMPError, ExempiLoadError
276
277
try:
278
xmpfile = XMPFiles(file_path="example.jpg")
279
xmp_data = xmpfile.get_xmp()
280
# ... work with XMP data
281
282
except ExempiLoadError:
283
print("Exempi library could not be loaded - check installation")
284
285
except XMPError as e:
286
if "Permission denied" in str(e):
287
print("File access denied - check file permissions")
288
elif "No such file" in str(e):
289
print("File not found - check file path")
290
else:
291
print(f"XMP operation failed: {e}")
292
293
except IOError as e:
294
print(f"File I/O error: {e}")
295
296
finally:
297
# Always close file if opened
298
if 'xmpfile' in locals():
299
try:
300
xmpfile.close_file()
301
except:
302
pass # Ignore close errors
303
```