0
# Module and Import System
1
2
Python module loading, creation, and import system access. This enables Java applications to work with Python modules and packages, create new modules, and manage the Python import system from Java code.
3
4
## Capabilities
5
6
### Module Creation and Management
7
8
Functions for creating and managing Python module objects.
9
10
```java { .api }
11
/**
12
* Create new module with object name
13
* @param name - Module name as PyObject
14
* @return New module object, or NULL on error
15
*/
16
public static native PyObject PyModule_NewObject(PyObject name);
17
18
/**
19
* Create new module with string name
20
* @param name - Module name as C string
21
* @return New module object, or NULL on error
22
*/
23
public static native PyObject PyModule_New(String name);
24
25
/**
26
* Get module's dictionary (namespace)
27
* @param module - Module object
28
* @return Module's __dict__ attribute (borrowed reference)
29
*/
30
public static native PyObject PyModule_GetDict(PyObject module);
31
32
/**
33
* Get module name as object
34
* @param module - Module object
35
* @return Module name object, or NULL on error
36
*/
37
public static native PyObject PyModule_GetNameObject(PyObject module);
38
39
/**
40
* Get module name as C string
41
* @param module - Module object
42
* @return Module name string, or NULL on error
43
*/
44
public static native String PyModule_GetName(PyObject module);
45
46
/**
47
* Get module filename object
48
* @param module - Module object
49
* @return Module filename object, or NULL on error
50
*/
51
public static native PyObject PyModule_GetFilenameObject(PyObject module);
52
53
/**
54
* Get module definition structure
55
* @param module - Module object
56
* @return Module definition, or NULL if not applicable
57
*/
58
public static native PyModuleDef PyModule_GetDef(PyObject module);
59
60
/**
61
* Get module state pointer
62
* @param module - Module object
63
* @return Module state pointer, or NULL on error
64
*/
65
public static native Pointer PyModule_GetState(PyObject module);
66
```
67
68
**Usage Example:**
69
70
```java
71
import static org.bytedeco.cpython.global.python.*;
72
73
// Create a new module
74
PyObject myModule = PyModule_New("mymodule");
75
if (myModule != null) {
76
// Get module dictionary for adding attributes
77
PyObject moduleDict = PyModule_GetDict(myModule);
78
79
// Add objects to module (see adding objects section below)
80
81
// Get module name
82
String name = PyModule_GetName(myModule);
83
System.out.println("Created module: " + name);
84
}
85
```
86
87
### Adding Objects to Modules
88
89
Functions for populating modules with attributes, functions, and constants.
90
91
```java { .api }
92
/**
93
* Add object to module (increments reference)
94
* @param module - Module object
95
* @param name - Attribute name
96
* @param value - Object to add
97
* @return 0 on success, -1 on error
98
*/
99
public static native int PyModule_AddObjectRef(PyObject module, String name, PyObject value);
100
101
/**
102
* Add object to module (convenience function)
103
* @param module - Module object
104
* @param name - Attribute name
105
* @param value - Object to add
106
* @return 0 on success, -1 on error
107
*/
108
public static native int PyModule_Add(PyObject module, String name, PyObject value);
109
110
/**
111
* Add object to module (steals reference)
112
* @param module - Module object
113
* @param name - Attribute name
114
* @param value - Object to add (reference stolen)
115
* @return 0 on success, -1 on error
116
*/
117
public static native int PyModule_AddObject(PyObject module, String name, PyObject value);
118
119
/**
120
* Add integer constant to module
121
* @param module - Module object
122
* @param name - Constant name
123
* @param value - Integer value
124
* @return 0 on success, -1 on error
125
*/
126
public static native int PyModule_AddIntConstant(PyObject module, String name, long value);
127
128
/**
129
* Add string constant to module
130
* @param module - Module object
131
* @param name - Constant name
132
* @param value - String value
133
* @return 0 on success, -1 on error
134
*/
135
public static native int PyModule_AddStringConstant(PyObject module, String name, String value);
136
```
137
138
**Usage Example:**
139
140
```java
141
// Create module and add various objects
142
PyObject module = PyModule_New("example");
143
144
// Add integer constant
145
PyModule_AddIntConstant(module, "VERSION", 100);
146
147
// Add string constant
148
PyModule_AddStringConstant(module, "AUTHOR", "Java Application");
149
150
// Add Python object
151
PyObject myList = PyList_New(0);
152
PyModule_AddObjectRef(module, "data", myList);
153
154
// Add function (assuming you have a function object)
155
PyObject myFunction = createPythonFunction();
156
PyModule_Add(module, "process", myFunction);
157
```
158
159
### Import System
160
161
Functions for importing and managing Python modules and packages.
162
163
```java { .api }
164
/**
165
* Import module by name (equivalent to 'import name')
166
* @param name - Module name
167
* @return Module object, or NULL on error
168
*/
169
public static native PyObject PyImport_ImportModule(String name);
170
171
/**
172
* Import module with full control (equivalent to __import__)
173
* @param name - Module name
174
* @param globals - Global namespace (or NULL)
175
* @param locals - Local namespace (or NULL)
176
* @param fromlist - From-list for relative imports (or NULL)
177
* @param level - Import level (0=absolute, >0=relative)
178
* @return Module object, or NULL on error
179
*/
180
public static native PyObject PyImport_ImportModuleLevel(String name, PyObject globals,
181
PyObject locals, PyObject fromlist, int level);
182
183
/**
184
* Import module using name object
185
* @param name - Module name as PyObject
186
* @return Module object, or NULL on error
187
*/
188
public static native PyObject PyImport_Import(PyObject name);
189
190
/**
191
* Reload existing module
192
* @param module - Module object to reload
193
* @return Reloaded module object, or NULL on error
194
*/
195
public static native PyObject PyImport_ReloadModule(PyObject module);
196
197
/**
198
* Import module without blocking on import lock
199
* @param name - Module name
200
* @return Module object, or NULL on error
201
*/
202
public static native PyObject PyImport_ImportModuleNoBlock(String name);
203
204
/**
205
* Import module from file path
206
* @param name - Module name
207
* @param pathname - Path to module file
208
* @param file - File object (or NULL)
209
* @return Module object, or NULL on error
210
*/
211
public static native PyObject PyImport_ImportModuleEx(String name, PyObject globals,
212
PyObject locals, PyObject fromlist);
213
```
214
215
**Usage Example:**
216
217
```java
218
// Import standard modules
219
PyObject sysModule = PyImport_ImportModule("sys");
220
PyObject osModule = PyImport_ImportModule("os");
221
222
if (sysModule != null) {
223
// Use sys module
224
PyObject sysPath = PyObject_GetAttrString(sysModule, "path");
225
System.out.println("Python sys.path imported successfully");
226
}
227
228
// Import with from-list (equivalent to 'from os import path')
229
PyObject fromList = PyList_New(1);
230
PyList_SetItem(fromList, 0, PyUnicode_FromString("path"));
231
PyObject osPath = PyImport_ImportModuleLevel("os", null, null, fromList, 0);
232
233
// Relative import (equivalent to 'from . import submodule')
234
PyObject relativeModule = PyImport_ImportModuleLevel("submodule",
235
null, null, null, 1);
236
```
237
238
### Import System State
239
240
Functions for accessing and managing the import system's internal state.
241
242
```java { .api }
243
/**
244
* Get dictionary of imported modules (sys.modules)
245
* @return Dictionary of all imported modules
246
*/
247
public static native PyObject PyImport_GetModuleDict();
248
249
/**
250
* Import frozen module (built-in module)
251
* @param name - Frozen module name
252
* @return 1 if imported, 0 if not found, -1 on error
253
*/
254
public static native int PyImport_ImportFrozenModule(String name);
255
256
/**
257
* Get import library file for dynamic loading
258
* @param name - Module name
259
* @return Module file path, or NULL if not found
260
*/
261
public static native String PyImport_GetMagicTag();
262
263
/**
264
* Execute module as script (__main__)
265
* @param module - Module object to execute
266
* @return 0 on success, -1 on error
267
*/
268
public static native int PyImport_ExecCodeModule(String name, PyObject co);
269
270
/**
271
* Execute module as script with filename
272
* @param name - Module name
273
* @param co - Code object to execute
274
* @param pathname - Path to module file
275
* @return Module object, or NULL on error
276
*/
277
public static native PyObject PyImport_ExecCodeModuleEx(String name, PyObject co, String pathname);
278
```
279
280
### Module Definition Structures
281
282
Key structures used for defining modules and their contents.
283
284
```java { .api }
285
/**
286
* Module definition structure
287
*/
288
class PyModuleDef extends Pointer {
289
// Contains:
290
// - Module name
291
// - Module documentation
292
// - Module size (-1 for single-phase init)
293
// - Method definitions
294
// - Slot definitions
295
// - Traverse function
296
// - Clear function
297
// - Free function
298
}
299
300
/**
301
* Base module definition structure
302
*/
303
class PyModuleDef_Base extends Pointer {
304
// Base fields for all module definitions
305
}
306
307
/**
308
* Module definition slot
309
*/
310
class PyModuleDef_Slot extends Pointer {
311
// Slot identifier and value for module initialization
312
}
313
314
/**
315
* Method definition structure
316
*/
317
class PyMethodDef extends Pointer {
318
// Contains:
319
// - Method name
320
// - Function pointer
321
// - Flags (METH_VARARGS, etc.)
322
// - Documentation string
323
}
324
```
325
326
## Advanced Module Management
327
328
### Module Search and Discovery
329
330
```java
331
public class ModuleDiscovery {
332
333
public static boolean isModuleAvailable(String moduleName) {
334
// Try to import module
335
PyObject module = PyImport_ImportModule(moduleName);
336
337
if (module != null) {
338
return true;
339
} else {
340
// Clear any import error
341
PyErr_Clear();
342
return false;
343
}
344
}
345
346
public static PyObject findModule(String name) {
347
// Check if already imported
348
PyObject modules = PyImport_GetModuleDict();
349
PyObject nameObj = PyUnicode_FromString(name);
350
PyObject existing = PyDict_GetItem(modules, nameObj);
351
352
if (existing != null) {
353
return existing; // Already imported
354
}
355
356
// Try to import
357
return PyImport_ImportModule(name);
358
}
359
}
360
```
361
362
### Dynamic Module Creation
363
364
```java
365
public class DynamicModule {
366
367
public static PyObject createCalculatorModule() {
368
// Create module
369
PyObject module = PyModule_New("calculator");
370
371
if (module == null) return null;
372
373
try {
374
// Add constants
375
PyModule_AddIntConstant(module, "PI_TIMES_100", 314);
376
PyModule_AddStringConstant(module, "VERSION", "1.0");
377
378
// Add data structures
379
PyObject operations = PyList_New(0);
380
PyList_Append(operations, PyUnicode_FromString("add"));
381
PyList_Append(operations, PyUnicode_FromString("subtract"));
382
PyModule_AddObjectRef(module, "operations", operations);
383
384
// Add to sys.modules so it can be imported later
385
PyObject modules = PyImport_GetModuleDict();
386
PyObject nameObj = PyUnicode_FromString("calculator");
387
PyDict_SetItem(modules, nameObj, module);
388
389
return module;
390
391
} catch (Exception e) {
392
return null;
393
}
394
}
395
}
396
```
397
398
### Module Reloading and Hot Updates
399
400
```java
401
public class ModuleReloader {
402
403
public static boolean reloadModule(String moduleName) {
404
// Get existing module
405
PyObject modules = PyImport_GetModuleDict();
406
PyObject nameObj = PyUnicode_FromString(moduleName);
407
PyObject existingModule = PyDict_GetItem(modules, nameObj);
408
409
if (existingModule == null) {
410
// Module not loaded, just import it
411
PyObject newModule = PyImport_ImportModule(moduleName);
412
return newModule != null;
413
}
414
415
// Reload existing module
416
PyObject reloaded = PyImport_ReloadModule(existingModule);
417
return reloaded != null;
418
}
419
420
public static void hotUpdateModule(String moduleName) {
421
// Remove from sys.modules to force reimport
422
PyObject modules = PyImport_GetModuleDict();
423
PyObject nameObj = PyUnicode_FromString(moduleName);
424
425
if (PyDict_Contains(modules, nameObj)) {
426
PyDict_DelItem(modules, nameObj);
427
}
428
429
// Re-import fresh copy
430
PyObject fresh = PyImport_ImportModule(moduleName);
431
432
if (fresh == null) {
433
System.err.println("Failed to hot update module: " + moduleName);
434
PyErr_Clear();
435
}
436
}
437
}
438
```
439
440
### Package and Namespace Management
441
442
```java
443
public class PackageManager {
444
445
public static PyObject createPackage(String packageName, String[] submodules) {
446
// Create main package module
447
PyObject package = PyModule_New(packageName);
448
if (package == null) return null;
449
450
// Set __path__ attribute for package
451
PyObject path = PyList_New(0);
452
PyModule_AddObjectRef(package, "__path__", path);
453
454
// Add to sys.modules
455
PyObject modules = PyImport_GetModuleDict();
456
PyObject nameObj = PyUnicode_FromString(packageName);
457
PyDict_SetItem(modules, nameObj, package);
458
459
// Create submodules
460
for (String submoduleName : submodules) {
461
String fullName = packageName + "." + submoduleName;
462
PyObject submodule = PyModule_New(fullName);
463
464
if (submodule != null) {
465
// Set __package__ attribute
466
PyModule_AddStringConstant(submodule, "__package__", packageName);
467
468
// Add to sys.modules
469
PyObject subNameObj = PyUnicode_FromString(fullName);
470
PyDict_SetItem(modules, subNameObj, submodule);
471
472
// Add reference in parent package
473
PyModule_AddObjectRef(package, submoduleName, submodule);
474
}
475
}
476
477
return package;
478
}
479
480
public static boolean importFromPackage(String packageName, String itemName) {
481
// Equivalent to 'from package import item'
482
PyObject fromList = PyList_New(1);
483
PyList_SetItem(fromList, 0, PyUnicode_FromString(itemName));
484
485
PyObject result = PyImport_ImportModuleLevel(packageName,
486
null, null, fromList, 0);
487
488
boolean success = (result != null);
489
if (!success) {
490
PyErr_Clear();
491
}
492
493
return success;
494
}
495
}
496
```
497
498
### Module Introspection
499
500
```java
501
public class ModuleIntrospection {
502
503
public static void inspectModule(PyObject module) {
504
if (module == null) return;
505
506
// Get module name
507
String name = PyModule_GetName(module);
508
System.out.println("Module: " + name);
509
510
// Get module dictionary
511
PyObject moduleDict = PyModule_GetDict(module);
512
513
// Get all attributes
514
PyObject keys = PyDict_Keys(moduleDict);
515
long keyCount = PyList_Size(keys);
516
517
System.out.println("Attributes (" + keyCount + "):");
518
for (long i = 0; i < keyCount; i++) {
519
PyObject key = PyList_GetItem(keys, i);
520
PyObject value = PyDict_GetItem(moduleDict, key);
521
522
String keyStr = PyUnicode_AsUTF8(key);
523
String typeStr = PyObject_GetAttrString(Py_TYPE(value), "__name__");
524
525
System.out.println(" " + keyStr + ": " + typeStr);
526
}
527
}
528
529
public static String[] getModuleAttributes(PyObject module) {
530
PyObject moduleDict = PyModule_GetDict(module);
531
PyObject keys = PyDict_Keys(moduleDict);
532
long count = PyList_Size(keys);
533
534
String[] attributes = new String[(int)count];
535
for (int i = 0; i < count; i++) {
536
PyObject key = PyList_GetItem(keys, i);
537
attributes[i] = PyUnicode_AsUTF8(key);
538
}
539
540
return attributes;
541
}
542
}
543
```
544
545
## Error Handling and Best Practices
546
547
### Safe Module Operations
548
549
```java
550
public class SafeModuleOperations {
551
552
public static PyObject safeImport(String moduleName) {
553
PyObject module = PyImport_ImportModule(moduleName);
554
555
if (module == null) {
556
// Handle import error
557
if (PyErr_Occurred() != null) {
558
System.err.println("Failed to import " + moduleName);
559
PyErr_Clear();
560
}
561
return null;
562
}
563
564
return module;
565
}
566
567
public static boolean safeAddToModule(PyObject module, String name, PyObject value) {
568
if (module == null || value == null) {
569
return false;
570
}
571
572
int result = PyModule_AddObjectRef(module, name, value);
573
574
if (result < 0) {
575
System.err.println("Failed to add " + name + " to module");
576
if (PyErr_Occurred() != null) {
577
PyErr_Clear();
578
}
579
return false;
580
}
581
582
return true;
583
}
584
}
585
```
586
587
### Module Cleanup
588
589
```java
590
public class ModuleCleanup {
591
592
public static void cleanupModule(String moduleName) {
593
// Remove from sys.modules
594
PyObject modules = PyImport_GetModuleDict();
595
PyObject nameObj = PyUnicode_FromString(moduleName);
596
597
if (PyDict_Contains(modules, nameObj)) {
598
PyDict_DelItem(modules, nameObj);
599
}
600
601
// Force garbage collection to clean up circular references
602
PyRun_SimpleString("import gc; gc.collect()");
603
}
604
}
605
```
606
607
## Integration Patterns
608
609
### Java-Python Module Bridge
610
611
```java
612
public class JavaPythonBridge {
613
614
public static PyObject createBridgeModule(String name, Object javaObject) {
615
PyObject module = PyModule_New(name);
616
617
if (module != null) {
618
// Add Java object wrapper
619
// This would typically involve creating Python objects
620
// that wrap Java functionality
621
622
// Add module metadata
623
PyModule_AddStringConstant(module, "__java_class__",
624
javaObject.getClass().getName());
625
626
// Add to Python's module system
627
PyObject modules = PyImport_GetModuleDict();
628
PyObject nameObj = PyUnicode_FromString(name);
629
PyDict_SetItem(modules, nameObj, module);
630
}
631
632
return module;
633
}
634
}
635
```
636
637
## Important Notes
638
639
### Reference Management
640
641
- `PyModule_AddObjectRef()` increments the reference count
642
- `PyModule_AddObject()` steals a reference
643
- Module dictionaries return borrowed references via `PyModule_GetDict()`
644
645
### Thread Safety
646
647
Module import operations are thread-safe, but module modification should be done carefully in multi-threaded environments.
648
649
### Performance Considerations
650
651
- Module imports can be expensive - cache imported modules when possible
652
- Use `PyImport_GetModuleDict()` to check if a module is already loaded
653
- Consider lazy loading for modules that may not always be needed
654
655
### Namespace Management
656
657
Modules added to `sys.modules` become available for import by Python code. Remove entries carefully to avoid breaking dependencies.