0
# Core Parsing and Writing
1
2
High-level functions providing the primary interface for reading, writing, and modifying Fortran namelist files. These functions handle automatic type conversion, format detection, and provide the most convenient access to f90nml functionality.
3
4
## Capabilities
5
6
### Reading Namelist Files
7
8
Parse Fortran namelist files from disk or file objects, automatically converting Fortran data types to equivalent Python types.
9
10
```python { .api }
11
def read(nml_path):
12
"""
13
Parse a Fortran namelist file and return its contents.
14
15
Args:
16
nml_path: str or file-like object - File path or file object to read from
17
18
Returns:
19
Namelist: Dictionary-like object containing parsed namelist data
20
21
Raises:
22
ValueError: If namelist syntax is invalid
23
IOError: If file cannot be read
24
"""
25
```
26
27
**Usage Examples:**
28
29
```python
30
# Read from file path
31
nml = f90nml.read('config.nml')
32
33
# Read from file object
34
with open('config.nml', 'r') as f:
35
nml = f90nml.read(f)
36
37
# Access nested values
38
input_file = nml['io_nml']['input_file']
39
timesteps = nml['run_nml']['timesteps']
40
```
41
42
### Reading Namelist Strings
43
44
Parse Fortran namelist data directly from strings, useful for processing embedded configurations or dynamically generated namelists.
45
46
```python { .api }
47
def reads(nml_string):
48
"""
49
Parse a Fortran namelist string and return its contents.
50
51
Args:
52
nml_string: str - String containing Fortran namelist syntax
53
54
Returns:
55
Namelist: Dictionary-like object containing parsed namelist data
56
57
Raises:
58
ValueError: If namelist syntax is invalid
59
"""
60
```
61
62
**Usage Examples:**
63
64
```python
65
# Parse simple namelist string
66
nml_str = '''
67
&run_config
68
timesteps = 100
69
dt = 0.01
70
output_freq = 10
71
/
72
'''
73
nml = f90nml.reads(nml_str)
74
75
# Parse complex data types
76
complex_str = '''
77
&data_nml
78
array = 1, 2, 3, 4, 5
79
matrix(1:2, 1:2) = 1.0, 2.0, 3.0, 4.0
80
use_feature = .true.
81
title = "Simulation Run"
82
/
83
'''
84
nml = f90nml.reads(complex_str)
85
```
86
87
### Writing Namelist Files
88
89
Save namelist data to disk with Fortran-compliant formatting, supporting both Namelist objects and Python dictionaries.
90
91
```python { .api }
92
def write(nml, nml_path, force=False, sort=False):
93
"""
94
Save a namelist to disk using file path or file object.
95
96
Args:
97
nml: Namelist or dict - Namelist data to write
98
nml_path: str or file-like object - Output path or file object
99
force: bool - Overwrite existing files (default: False)
100
sort: bool - Sort namelist groups and variables alphabetically (default: False)
101
102
Raises:
103
IOError: If file exists and force=False, or file cannot be written
104
TypeError: If nml is not a valid namelist or dict
105
"""
106
```
107
108
**Usage Examples:**
109
110
```python
111
# Write to file path
112
nml = f90nml.read('input.nml')
113
nml['run_nml']['timesteps'] = 200
114
f90nml.write(nml, 'output.nml')
115
116
# Write to file object
117
with open('output.nml', 'w') as f:
118
f90nml.write(nml, f)
119
120
# Force overwrite existing file
121
f90nml.write(nml, 'output.nml', force=True)
122
123
# Write with sorted keys
124
f90nml.write(nml, 'output.nml', sort=True)
125
126
# Write Python dict as namelist
127
data = {
128
'config': {
129
'param1': 10,
130
'param2': 'value',
131
'param3': [1, 2, 3]
132
}
133
}
134
f90nml.write(data, 'generated.nml')
135
```
136
137
### Patching Namelists
138
139
Create modified versions of existing namelist files while preserving original formatting, comments, and structure. This is ideal for parameter studies and configuration management.
140
141
```python { .api }
142
def patch(nml_path, nml_patch, out_path=None):
143
"""
144
Create a new namelist based on input namelist and reference dict.
145
146
Args:
147
nml_path: str - Path to original namelist file
148
nml_patch: dict - Dictionary of values to modify or add
149
out_path: str, optional - Output file path (default: input_path + '~')
150
151
Returns:
152
Namelist: The patched namelist object
153
154
Raises:
155
IOError: If input file cannot be read or output file cannot be written
156
ValueError: If patch contains invalid namelist data
157
"""
158
```
159
160
**Usage Examples:**
161
162
```python
163
# Simple value patching
164
patch_data = {
165
'run_config': {
166
'timesteps': 500,
167
'output_freq': 25
168
}
169
}
170
result = f90nml.patch('input.nml', patch_data, 'modified.nml')
171
172
# Patch with default output naming (input.nml -> input.nml~)
173
f90nml.patch('config.nml', patch_data)
174
175
# Add new variables to existing groups
176
patch_data = {
177
'existing_group': {
178
'new_parameter': 42,
179
'existing_parameter': 'updated_value'
180
}
181
}
182
f90nml.patch('base.nml', patch_data, 'patched.nml')
183
184
# Complex data type patching
185
complex_patch = {
186
'arrays_nml': {
187
'pressure_levels': [1000, 850, 700, 500, 300, 200, 100],
188
'use_advanced_solver': True,
189
'solver_tolerance': 1e-6
190
}
191
}
192
f90nml.patch('model.nml', complex_patch, 'updated_model.nml')
193
```
194
195
## Data Type Conversion
196
197
f90nml automatically converts between Fortran and Python data types:
198
199
**Fortran → Python:**
200
- `.true./.false.` → `True/False`
201
- `123` → `123` (int)
202
- `1.23` → `1.23` (float)
203
- `'string'` → `'string'` (str)
204
- `1, 2, 3` → `[1, 2, 3]` (list)
205
- `(1.0, 2.0)` → `complex(1.0, 2.0)`
206
207
**Python → Fortran:**
208
- `True/False` → `.true./.false.`
209
- `123` → `123`
210
- `1.23` → `1.23`
211
- `'string'` → `'string'`
212
- `[1, 2, 3]` → `1, 2, 3`
213
- `complex(1.0, 2.0)` → `(1.0, 2.0)`
214
215
## Error Handling
216
217
Common error scenarios and their handling:
218
219
```python
220
# Handle file not found
221
try:
222
nml = f90nml.read('nonexistent.nml')
223
except IOError as e:
224
print(f"File error: {e}")
225
226
# Handle invalid namelist syntax
227
try:
228
nml = f90nml.reads('&invalid syntax')
229
except ValueError as e:
230
print(f"Parse error: {e}")
231
232
# Handle file overwrite protection
233
try:
234
f90nml.write(nml, 'existing.nml')
235
except IOError as e:
236
print(f"File exists, use force=True to overwrite")
237
f90nml.write(nml, 'existing.nml', force=True)
238
```