summaryrefslogtreecommitdiff
path: root/Doc/c-api/init_config.rst
blob: 325e60706167e4340a567cf52e2f6b33f54e7887 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
.. highlight:: c

.. _init-config:

***********************************
Python Initialization Configuration
***********************************

.. versionadded:: 3.8

Python can be initialized with :c:func:`Py_InitializeFromConfig` and the
:c:type:`PyConfig` structure. It can be preinitialized with
:c:func:`Py_PreInitialize` and the :c:type:`PyPreConfig` structure.

There are two kinds of configuration:

* The :ref:`Python Configuration <init-python-config>` can be used to build a
  customized Python which behaves as the regular Python. For example,
  environments variables and command line arguments are used to configure
  Python.

* The :ref:`Isolated Configuration <init-isolated-conf>` can be used to embed
  Python into an application. It isolates Python from the system. For example,
  environments variables are ignored, the LC_CTYPE locale is left unchanged and
  no signal handler is registred.

The :c:func:`Py_RunMain` function can be used to write a customized Python
program.

See also :ref:`Initialization, Finalization, and Threads <initialization>`.

.. seealso::
   :pep:`587` "Python Initialization Configuration".


Example
=======

Example of customized Python always running in isolated mode::

    int main(int argc, char **argv)
    {
        PyStatus status;

        PyConfig config;
        PyConfig_InitPythonConfig(&config);
        config.isolated = 1;

        /* Decode command line arguments.
           Implicitly preinitialize Python (in isolated mode). */
        status = PyConfig_SetBytesArgv(&config, argc, argv);
        if (PyStatus_Exception(status)) {
            goto exception;
        }

        status = Py_InitializeFromConfig(&config);
        if (PyStatus_Exception(status)) {
            goto exception;
        }
        PyConfig_Clear(&config);

        return Py_RunMain();

    exception:
        PyConfig_Clear(&config);
        if (PyStatus_IsExit(status)) {
            return status.exitcode;
        }
        /* Display the error message and exit the process with
           non-zero exit code */
        Py_ExitStatusException(status);
    }


PyWideStringList
================

.. c:type:: PyWideStringList

   List of ``wchar_t*`` strings.

   If *length* is non-zero, *items* must be non-``NULL`` and all strings must be
   non-``NULL``.

   Methods:

   .. c:function:: PyStatus PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)

      Append *item* to *list*.

      Python must be preinitialized to call this function.

   .. c:function:: PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item)

      Insert *item* into *list* at *index*.

      If *index* is greater than or equal to *list* length, append *item* to
      *list*.

      *index* must be greater than or equal to 0.

      Python must be preinitialized to call this function.

   Structure fields:

   .. c:member:: Py_ssize_t length

      List length.

   .. c:member:: wchar_t** items

      List items.

PyStatus
========

.. c:type:: PyStatus

   Structure to store an initialization function status: success, error
   or exit.

   For an error, it can store the C function name which created the error.

   Structure fields:

   .. c:member:: int exitcode

      Exit code. Argument passed to ``exit()``.

   .. c:member:: const char *err_msg

      Error message.

   .. c:member:: const char *func

      Name of the function which created an error, can be ``NULL``.

   Functions to create a status:

   .. c:function:: PyStatus PyStatus_Ok(void)

      Success.

   .. c:function:: PyStatus PyStatus_Error(const char *err_msg)

      Initialization error with a message.

      *err_msg* must not be ``NULL``.

   .. c:function:: PyStatus PyStatus_NoMemory(void)

      Memory allocation failure (out of memory).

   .. c:function:: PyStatus PyStatus_Exit(int exitcode)

      Exit Python with the specified exit code.

   Functions to handle a status:

   .. c:function:: int PyStatus_Exception(PyStatus status)

      Is the status an error or an exit? If true, the exception must be
      handled; by calling :c:func:`Py_ExitStatusException` for example.

   .. c:function:: int PyStatus_IsError(PyStatus status)

      Is the result an error?

   .. c:function:: int PyStatus_IsExit(PyStatus status)

      Is the result an exit?

   .. c:function:: void Py_ExitStatusException(PyStatus status)

      Call ``exit(exitcode)`` if *status* is an exit. Print the error
      message and exit with a non-zero exit code if *status* is an error.  Must
      only be called if ``PyStatus_Exception(status)`` is non-zero.

.. note::
   Internally, Python uses macros which set ``PyStatus.func``,
   whereas functions to create a status set ``func`` to ``NULL``.

Example::

    PyStatus alloc(void **ptr, size_t size)
    {
        *ptr = PyMem_RawMalloc(size);
        if (*ptr == NULL) {
            return PyStatus_NoMemory();
        }
        return PyStatus_Ok();
    }

    int main(int argc, char **argv)
    {
        void *ptr;
        PyStatus status = alloc(&ptr, 16);
        if (PyStatus_Exception(status)) {
            Py_ExitStatusException(status);
        }
        PyMem_Free(ptr);
        return 0;
    }


PyPreConfig
===========

.. c:type:: PyPreConfig

   Structure used to preinitialize Python.

   Function to initialize a preconfiguration:

   .. c:function:: void PyPreConfig_InitPythonConfig(PyPreConfig *preconfig)

      Initialize the preconfiguration with :ref:`Python Configuration
      <init-python-config>`.

   .. c:function:: void PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig)

      Initialize the preconfiguration with :ref:`Isolated Configuration
      <init-isolated-conf>`.

   Structure fields:

   .. c:member:: int allocator

      Name of the Python memory allocators:

      * ``PYMEM_ALLOCATOR_NOT_SET`` (``0``): don't change memory allocators
        (use defaults)
      * ``PYMEM_ALLOCATOR_DEFAULT`` (``1``): default memory allocators
      * ``PYMEM_ALLOCATOR_DEBUG`` (``2``): default memory allocators with
        debug hooks
      * ``PYMEM_ALLOCATOR_MALLOC`` (``3``): force usage of ``malloc()``
      * ``PYMEM_ALLOCATOR_MALLOC_DEBUG`` (``4``): force usage of
        ``malloc()`` with debug hooks
      * ``PYMEM_ALLOCATOR_PYMALLOC`` (``5``): :ref:`Python pymalloc memory
        allocator <pymalloc>`
      * ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` (``6``): :ref:`Python pymalloc
        memory allocator <pymalloc>` with debug hooks

      ``PYMEM_ALLOCATOR_PYMALLOC`` and ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` are
      not supported if Python is :option:`configured using --without-pymalloc
      <--without-pymalloc>`.

      See :ref:`Memory Management <memory>`.

      Default: ``PYMEM_ALLOCATOR_NOT_SET``.

   .. c:member:: int configure_locale

      Set the LC_CTYPE locale to the user preferred locale?

      If equals to 0, set :c:member:`~PyPreConfig.coerce_c_locale` and
      :c:member:`~PyPreConfig.coerce_c_locale_warn` members to 0.

      See the :term:`locale encoding`.

      Default: ``1`` in Python config, ``0`` in isolated config.

   .. c:member:: int coerce_c_locale

      If equals to 2, coerce the C locale.

      If equals to 1, read the LC_CTYPE locale to decide if it should be
      coerced.

      See the :term:`locale encoding`.

      Default: ``-1`` in Python config, ``0`` in isolated config.

   .. c:member:: int coerce_c_locale_warn

      If non-zero, emit a warning if the C locale is coerced.

      Default: ``-1`` in Python config, ``0`` in isolated config.

   .. c:member:: int dev_mode

      If non-zero, enables the :ref:`Python Development Mode <devmode>`:
      see :c:member:`PyConfig.dev_mode`.

      Default: ``-1`` in Python mode, ``0`` in isolated mode.

   .. c:member:: int isolated

      Isolated mode: see :c:member:`PyConfig.isolated`.

      Default: ``0`` in Python mode, ``1`` in isolated mode.

   .. c:member:: int legacy_windows_fs_encoding

      If non-zero:

      * Set :c:member:`PyPreConfig.utf8_mode` to ``0``,
      * Set :c:member:`PyConfig.filesystem_encoding` to ``"mbcs"``,
      * Set :c:member:`PyConfig.filesystem_errors` to ``"replace"``.

      Initialized the from :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment
      variable value.

      Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
      Windows specific code.

      Default: ``0``.

   .. c:member:: int parse_argv

      If non-zero, :c:func:`Py_PreInitializeFromArgs` and
      :c:func:`Py_PreInitializeFromBytesArgs` parse their ``argv`` argument the
      same way the regular Python parses command line arguments: see
      :ref:`Command Line Arguments <using-on-cmdline>`.

      Default: ``1`` in Python config, ``0`` in isolated config.

   .. c:member:: int use_environment

      Use :ref:`environment variables <using-on-envvars>`? See
      :c:member:`PyConfig.use_environment`.

      Default: ``1`` in Python config and ``0`` in isolated config.

   .. c:member:: int utf8_mode

      If non-zero, enable the :ref:`Python UTF-8 Mode <utf8-mode>`.

      Set by the :option:`-X utf8 <-X>` command line option and the
      :envvar:`PYTHONUTF8` environment variable.

      Default: ``-1`` in Python config and ``0`` in isolated config.


.. _c-preinit:

Preinitialize Python with PyPreConfig
=====================================

The preinitialization of Python:

* Set the Python memory allocators (:c:member:`PyPreConfig.allocator`)
* Configure the LC_CTYPE locale (:term:`locale encoding`)
* Set the :ref:`Python UTF-8 Mode <utf8-mode>`
  (:c:member:`PyPreConfig.utf8_mode`)

The current preconfiguration (``PyPreConfig`` type) is stored in
``_PyRuntime.preconfig``.

Functions to preinitialize Python:

.. c:function:: PyStatus Py_PreInitialize(const PyPreConfig *preconfig)

   Preinitialize Python from *preconfig* preconfiguration.

   *preconfig* must not be ``NULL``.

.. c:function:: PyStatus Py_PreInitializeFromBytesArgs(const PyPreConfig *preconfig, int argc, char * const *argv)

   Preinitialize Python from *preconfig* preconfiguration.

   Parse *argv* command line arguments (bytes strings) if
   :c:member:`~PyPreConfig.parse_argv` of *preconfig* is non-zero.

   *preconfig* must not be ``NULL``.

.. c:function:: PyStatus Py_PreInitializeFromArgs(const PyPreConfig *preconfig, int argc, wchar_t * const * argv)

   Preinitialize Python from *preconfig* preconfiguration.

   Parse *argv* command line arguments (wide strings) if
   :c:member:`~PyPreConfig.parse_argv` of *preconfig* is non-zero.

   *preconfig* must not be ``NULL``.

The caller is responsible to handle exceptions (error or exit) using
:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.

For :ref:`Python Configuration <init-python-config>`
(:c:func:`PyPreConfig_InitPythonConfig`), if Python is initialized with
command line arguments, the command line arguments must also be passed to
preinitialize Python, since they have an effect on the pre-configuration
like encodings. For example, the :option:`-X utf8 <-X>` command line option
enables the :ref:`Python UTF-8 Mode <utf8-mode>`.

``PyMem_SetAllocator()`` can be called after :c:func:`Py_PreInitialize` and
before :c:func:`Py_InitializeFromConfig` to install a custom memory allocator.
It can be called before :c:func:`Py_PreInitialize` if
:c:member:`PyPreConfig.allocator` is set to ``PYMEM_ALLOCATOR_NOT_SET``.

Python memory allocation functions like :c:func:`PyMem_RawMalloc` must not be
used before the Python preinitialization, whereas calling directly ``malloc()``
and ``free()`` is always safe. :c:func:`Py_DecodeLocale` must not be called
before the Python preinitialization.

Example using the preinitialization to enable
the :ref:`Python UTF-8 Mode <utf8-mode>`::

    PyStatus status;
    PyPreConfig preconfig;
    PyPreConfig_InitPythonConfig(&preconfig);

    preconfig.utf8_mode = 1;

    status = Py_PreInitialize(&preconfig);
    if (PyStatus_Exception(status)) {
        Py_ExitStatusException(status);
    }

    /* at this point, Python speaks UTF-8 */

    Py_Initialize();
    /* ... use Python API here ... */
    Py_Finalize();


PyConfig
========

.. c:type:: PyConfig

   Structure containing most parameters to configure Python.

   When done, the :c:func:`PyConfig_Clear` function must be used to release the
   configuration memory.

   Structure methods:

   .. c:function:: void PyConfig_InitPythonConfig(PyConfig *config)

      Initialize configuration with the :ref:`Python Configuration
      <init-python-config>`.

   .. c:function:: void PyConfig_InitIsolatedConfig(PyConfig *config)

      Initialize configuration with the :ref:`Isolated Configuration
      <init-isolated-conf>`.

   .. c:function:: PyStatus PyConfig_SetString(PyConfig *config, wchar_t * const *config_str, const wchar_t *str)

      Copy the wide character string *str* into ``*config_str``.

      :ref:`Preinitialize Python <c-preinit>` if needed.

   .. c:function:: PyStatus PyConfig_SetBytesString(PyConfig *config, wchar_t * const *config_str, const char *str)

      Decode *str* using :c:func:`Py_DecodeLocale` and set the result into
      ``*config_str``.

      :ref:`Preinitialize Python <c-preinit>` if needed.

   .. c:function:: PyStatus PyConfig_SetArgv(PyConfig *config, int argc, wchar_t * const *argv)

      Set command line arguments (:c:member:`~PyConfig.argv` member of
      *config*) from the *argv* list of wide character strings.

      :ref:`Preinitialize Python <c-preinit>` if needed.

   .. c:function:: PyStatus PyConfig_SetBytesArgv(PyConfig *config, int argc, char * const *argv)

      Set command line arguments (:c:member:`~PyConfig.argv` member of
      *config*) from the *argv* list of bytes strings. Decode bytes using
      :c:func:`Py_DecodeLocale`.

      :ref:`Preinitialize Python <c-preinit>` if needed.

   .. c:function:: PyStatus PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list, Py_ssize_t length, wchar_t **items)

      Set the list of wide strings *list* to *length* and *items*.

      :ref:`Preinitialize Python <c-preinit>` if needed.

   .. c:function:: PyStatus PyConfig_Read(PyConfig *config)

      Read all Python configuration.

      Fields which are already initialized are left unchanged.

      The :c:func:`PyConfig_Read` function only parses
      :c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
      is set to ``2`` after arguments are parsed. Since Python arguments are
      strippped from :c:member:`PyConfig.argv`, parsing arguments twice would
      parse the application options as Python options.

      :ref:`Preinitialize Python <c-preinit>` if needed.

      .. versionchanged:: 3.10
         The :c:member:`PyConfig.argv` arguments are now only parsed once,
         :c:member:`PyConfig.parse_argv` is set to ``2`` after arguments are
         parsed, and arguments are only parsed if
         :c:member:`PyConfig.parse_argv` equals ``1``.

   .. c:function:: void PyConfig_Clear(PyConfig *config)

      Release configuration memory.

   Most ``PyConfig`` methods :ref:`preinitialize Python <c-preinit>` if needed.
   In that case, the Python preinitialization configuration
   (:c:type:`PyPreConfig`) in based on the :c:type:`PyConfig`. If configuration
   fields which are in common with :c:type:`PyPreConfig` are tuned, they must
   be set before calling a :c:type:`PyConfig` method:

   * :c:member:`PyConfig.dev_mode`
   * :c:member:`PyConfig.isolated`
   * :c:member:`PyConfig.parse_argv`
   * :c:member:`PyConfig.use_environment`

   Moreover, if :c:func:`PyConfig_SetArgv` or :c:func:`PyConfig_SetBytesArgv`
   is used, this method must be called before other methods, since the
   preinitialization configuration depends on command line arguments (if
   :c:member:`parse_argv` is non-zero).

   The caller of these methods is responsible to handle exceptions (error or
   exit) using ``PyStatus_Exception()`` and ``Py_ExitStatusException()``.

   Structure fields:

   .. c:member:: PyWideStringList argv

      Command line arguments: :data:`sys.argv`.

      Set :c:member:`~PyConfig.parse_argv` to ``1`` to parse
      :c:member:`~PyConfig.argv` the same way the regular Python parses Python
      command line arguments and then to strip Python arguments from
      :c:member:`~PyConfig.argv`.

      If :c:member:`~PyConfig.argv` is empty, an empty string is added to
      ensure that :data:`sys.argv` always exists and is never empty.

      Default: ``NULL``.

      See also the :c:member:`~PyConfig.orig_argv` member.

   .. c:member:: wchar_t* base_exec_prefix

      :data:`sys.base_exec_prefix`.

      Default: ``NULL``.

      Part of the :ref:`Python Path Configuration <init-path-config>` output.

   .. c:member:: wchar_t* base_executable

      Python base executable: :data:`sys._base_executable`.

      Set by the :envvar:`__PYVENV_LAUNCHER__` environment variable.

      Set from :c:member:`PyConfig.executable` if ``NULL``.

      Default: ``NULL``.

      Part of the :ref:`Python Path Configuration <init-path-config>` output.

   .. c:member:: wchar_t* base_prefix

      :data:`sys.base_prefix`.

      Default: ``NULL``.

      Part of the :ref:`Python Path Configuration <init-path-config>` output.

   .. c:member:: int buffered_stdio

      If equals to 0 and :c:member:`~PyConfig.configure_c_stdio` is non-zero,
      disable buffering on the C streams stdout and stderr.

      Set to 0 by the :option:`-u` command line option and the
      :envvar:`PYTHONUNBUFFERED` environment variable.

      stdin is always opened in buffered mode.

      Default: ``1``.

   .. c:member:: int bytes_warning

      If equals to 1, issue a warning when comparing :class:`bytes` or
      :class:`bytearray` with :class:`str`, or comparing :class:`bytes` with
      :class:`int`.

      If equal or greater to 2, raise a :exc:`BytesWarning` exception in these
      cases.

      Incremented by the :option:`-b` command line option.

      Default: ``0``.

   .. c:member:: int warn_default_encoding

      If non-zero, emit a :exc:`EncodingWarning` warning when :class:`io.TextIOWrapper`
      uses its default encoding. See :ref:`io-encoding-warning` for details.

      Default: ``0``.

      .. versionadded:: 3.10

   .. c:member:: wchar_t* check_hash_pycs_mode

      Control the validation behavior of hash-based ``.pyc`` files:
      value of the :option:`--check-hash-based-pycs` command line option.

      Valid values:

      - ``L"always"``: Hash the source file for invalidation regardless of
        value of the 'check_source' flag.
      - ``L"never"``: Assume that hash-based pycs always are valid.
      - ``L"default"``: The 'check_source' flag in hash-based pycs
        determines invalidation.

      Default: ``L"default"``.

      See also :pep:`552` "Deterministic pycs".

   .. c:member:: int configure_c_stdio

      If non-zero, configure C standard streams:

      * On Windows, set the binary mode (``O_BINARY``) on stdin, stdout and
        stderr.
      * If :c:member:`~PyConfig.buffered_stdio` equals zero, disable buffering
        of stdin, stdout and stderr streams.
      * If :c:member:`~PyConfig.interactive` is non-zero, enable stream
        buffering on stdin and stdout (only stdout on Windows).

      Default: ``1`` in Python config, ``0`` in isolated config.

   .. c:member:: int dev_mode

      If non-zero, enable the :ref:`Python Development Mode <devmode>`.

      Default: ``-1`` in Python mode, ``0`` in isolated mode.

   .. c:member:: int dump_refs

      Dump Python refererences?

      If non-zero, dump all objects which are still alive at exit.

      Set to ``1`` by the :envvar:`PYTHONDUMPREFS` environment variable.

      Need a special build of Python with the ``Py_TRACE_REFS`` macro defined:
      see the :option:`configure --with-trace-refs option <--with-trace-refs>`.

      Default: ``0``.

   .. c:member:: wchar_t* exec_prefix

      The site-specific directory prefix where the platform-dependent Python
      files are installed: :data:`sys.exec_prefix`.

      Default: ``NULL``.

      Part of the :ref:`Python Path Configuration <init-path-config>` output.

   .. c:member:: wchar_t* executable

      The absolute path of the executable binary for the Python interpreter:
      :data:`sys.executable`.

      Default: ``NULL``.

      Part of the :ref:`Python Path Configuration <init-path-config>` output.

   .. c:member:: int faulthandler

      Enable faulthandler?

      If non-zero, call :func:`faulthandler.enable` at startup.

      Set to ``1`` by :option:`-X faulthandler <-X>` and the
      :envvar:`PYTHONFAULTHANDLER` environment variable.

      Default: ``-1`` in Python mode, ``0`` in isolated mode.

   .. c:member:: wchar_t* filesystem_encoding

      :term:`Filesystem encoding <filesystem encoding and error handler>`:
      :func:`sys.getfilesystemencoding`.

      On macOS, Android and VxWorks: use ``"utf-8"`` by default.

      On Windows: use ``"utf-8"`` by default, or ``"mbcs"`` if
      :c:member:`~PyPreConfig.legacy_windows_fs_encoding` of
      :c:type:`PyPreConfig` is non-zero.

      Default encoding on other platforms:

      * ``"utf-8"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero.
      * ``"ascii"`` if Python detects that ``nl_langinfo(CODESET)`` announces
        the ASCII encoding (or Roman8 encoding on HP-UX), whereas the
        ``mbstowcs()`` function decodes from a different encoding (usually
        Latin1).
      * ``"utf-8"`` if ``nl_langinfo(CODESET)`` returns an empty string.
      * Otherwise, use the :term:`locale encoding`:
        ``nl_langinfo(CODESET)`` result.

      At Python statup, the encoding name is normalized to the Python codec
      name. For example, ``"ANSI_X3.4-1968"`` is replaced with ``"ascii"``.

      See also the :c:member:`~PyConfig.filesystem_errors` member.

   .. c:member:: wchar_t* filesystem_errors

      :term:`Filesystem error handler <filesystem encoding and error handler>`:
      :func:`sys.getfilesystemencodeerrors`.

      On Windows: use ``"surrogatepass"`` by default, or ``"replace"``  if
      :c:member:`~PyPreConfig.legacy_windows_fs_encoding` of
      :c:type:`PyPreConfig` is non-zero.

      On other platforms: use ``"surrogateescape"`` by default.

      Supported error handlers:

      * ``"strict"``
      * ``"surrogateescape"``
      * ``"surrogatepass"`` (only supported with the UTF-8 encoding)

      See also the :c:member:`~PyConfig.filesystem_encoding` member.

   .. c:member:: unsigned long hash_seed
   .. c:member:: int use_hash_seed

      Randomized hash function seed.

      If :c:member:`~PyConfig.use_hash_seed` is zero, a seed is chosen randomly
      at Python startup, and :c:member:`~PyConfig.hash_seed` is ignored.

      Set by the :envvar:`PYTHONHASHSEED` environment variable.

      Default *use_hash_seed* value: ``-1`` in Python mode, ``0`` in isolated
      mode.

   .. c:member:: wchar_t* home

      Python home directory.

      If :c:func:`Py_SetPythonHome` has been called, use its argument if it is
      not ``NULL``.

      Set by the :envvar:`PYTHONHOME` environment variable.

      Default: ``NULL``.

      Part of the :ref:`Python Path Configuration <init-path-config>` input.

   .. c:member:: int import_time

      If non-zero, profile import time.

      Set the ``1`` by the :option:`-X importtime <-X>` option and the
      :envvar:`PYTHONPROFILEIMPORTTIME` environment variable.

      Default: ``0``.

   .. c:member:: int inspect

      Enter interactive mode after executing a script or a command.

      If greater than 0, enable inspect: when a script is passed as first
      argument or the -c option is used, enter interactive mode after executing
      the script or the command, even when :data:`sys.stdin` does not appear to
      be a terminal.

      Incremented by the :option:`-i` command line option. Set to ``1`` if the
      :envvar:`PYTHONINSPECT` environment variable is non-empty.

      Default: ``0``.

   .. c:member:: int install_signal_handlers

      Install Python signal handlers?

      Default: ``1`` in Python mode, ``0`` in isolated mode.

   .. c:member:: int interactive

      If greater than 0, enable the interactive mode (REPL).

      Incremented by the :option:`-i` command line option.

      Default: ``0``.

   .. c:member:: int isolated

      If greater than 0, enable isolated mode:

      * :data:`sys.path` contains neither the script's directory (computed from
        ``argv[0]`` or the current directory) nor the user's site-packages
        directory.
      * Python REPL doesn't import :mod:`readline` nor enable default readline
        configuration on interactive prompts.
      * Set :c:member:`~PyConfig.use_environment` and
        :c:member:`~PyConfig.user_site_directory` to 0.

      Default: ``0`` in Python mode, ``1`` in isolated mode.

      See also :c:member:`PyPreConfig.isolated`.

   .. c:member:: int legacy_windows_stdio

      If non-zero, use :class:`io.FileIO` instead of
      :class:`io.WindowsConsoleIO` for :data:`sys.stdin`, :data:`sys.stdout`
      and :data:`sys.stderr`.

      Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSSTDIO` environment
      variable is set to a non-empty string.

      Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
      Windows specific code.

      Default: ``0``.

      See also the :pep:`528` (Change Windows console encoding to UTF-8).

   .. c:member:: int malloc_stats

      If non-zero, dump statistics on :ref:`Python pymalloc memory allocator
      <pymalloc>` at exit.

      Set to ``1`` by the :envvar:`PYTHONMALLOCSTATS` environment variable.

      The option is ignored if Python is :option:`configured using
      the --without-pymalloc option <--without-pymalloc>`.

      Default: ``0``.

   .. c:member:: wchar_t* platlibdir

      Platform library directory name: :data:`sys.platlibdir`.

      Set by the :envvar:`PYTHONPLATLIBDIR` environment variable.

      Default: value of the ``PLATLIBDIR`` macro which is set by the
      :option:`configure --with-platlibdir option <--with-platlibdir>`
      (default: ``"lib"``).

      Part of the :ref:`Python Path Configuration <init-path-config>` input.

      .. versionadded:: 3.9

   .. c:member:: wchar_t* pythonpath_env

      Module search paths (:data:`sys.path`) as a string separated by ``DELIM``
      (:data:`os.path.pathsep`).

      Set by the :envvar:`PYTHONPATH` environment variable.

      Default: ``NULL``.

      Part of the :ref:`Python Path Configuration <init-path-config>` input.

   .. c:member:: PyWideStringList module_search_paths
   .. c:member:: int module_search_paths_set

      Module search paths: :data:`sys.path`.

      If :c:member:`~PyConfig.module_search_paths_set` is equal to 0, the
      function calculating the :ref:`Python Path Configuration <init-path-config>`
      overrides the :c:member:`~PyConfig.module_search_paths` and sets
      :c:member:`~PyConfig.module_search_paths_set` to ``1``.

      Default: empty list (``module_search_paths``) and ``0``
      (``module_search_paths_set``).

      Part of the :ref:`Python Path Configuration <init-path-config>` output.

   .. c:member:: int optimization_level

      Compilation optimization level:

      * ``0``: Peephole optimizer, set ``__debug__`` to ``True``.
      * ``1``: Level 0, remove assertions, set ``__debug__`` to ``False``.
      * ``2``: Level 1, strip docstrings.

      Incremented by the :option:`-O` command line option. Set to the
      :envvar:`PYTHONOPTIMIZE` environment variable value.

      Default: ``0``.

   .. c:member:: PyWideStringList orig_argv

      The list of the original command line arguments passed to the Python
      executable: :data:`sys.orig_argv`.

      If :c:member:`~PyConfig.orig_argv` list is empty and
      :c:member:`~PyConfig.argv` is not a list only containing an empty
      string, :c:func:`PyConfig_Read` copies :c:member:`~PyConfig.argv` into
      :c:member:`~PyConfig.orig_argv` before modifying
      :c:member:`~PyConfig.argv` (if :c:member:`~PyConfig.parse_argv` is
      non-zero).

      See also the :c:member:`~PyConfig.argv` member and the
      :c:func:`Py_GetArgcArgv` function.

      Default: empty list.

      .. versionadded:: 3.10

   .. c:member:: int parse_argv

      Parse command line arguments?

      If equals to ``1``, parse :c:member:`~PyConfig.argv` the same way the regular
      Python parses :ref:`command line arguments <using-on-cmdline>`, and strip
      Python arguments from :c:member:`~PyConfig.argv`.

      The :c:func:`PyConfig_Read` function only parses
      :c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
      is set to ``2`` after arguments are parsed. Since Python arguments are
      strippped from :c:member:`PyConfig.argv`, parsing arguments twice would
      parse the application options as Python options.

      Default: ``1`` in Python mode, ``0`` in isolated mode.

      .. versionchanged:: 3.10
         The :c:member:`PyConfig.argv` arguments are now only parsed if
         :c:member:`PyConfig.parse_argv` equals to ``1``.

   .. c:member:: int parser_debug

      Parser debug mode. If greater than 0, turn on parser debugging output (for expert only, depending
      on compilation options).

      Incremented by the :option:`-d` command line option. Set to the
      :envvar:`PYTHONDEBUG` environment variable value.

      Default: ``0``.

   .. c:member:: int pathconfig_warnings

      On Unix, if non-zero, calculating the :ref:`Python Path Configuration
      <init-path-config>` can log warnings into ``stderr``. If equals to 0,
      suppress these warnings.

      It has no effect on Windows.

      Default: ``1`` in Python mode, ``0`` in isolated mode.

      Part of the :ref:`Python Path Configuration <init-path-config>` input.

   .. c:member:: wchar_t* prefix

      The site-specific directory prefix where the platform independent Python
      files are installed: :data:`sys.prefix`.

      Default: ``NULL``.

      Part of the :ref:`Python Path Configuration <init-path-config>` output.

   .. c:member:: wchar_t* program_name

      Program name used to initialize :c:member:`~PyConfig.executable` and in
      early error messages during Python initialization.

      * If :func:`Py_SetProgramName` has been called, use its argument.
      * On macOS, use :envvar:`PYTHONEXECUTABLE` environment variable if set.
      * If the ``WITH_NEXT_FRAMEWORK`` macro is defined, use
        :envvar:`__PYVENV_LAUNCHER__` environment variable if set.
      * Use ``argv[0]`` of :c:member:`~PyConfig.argv` if available and
        non-empty.
      * Otherwise, use ``L"python"`` on Windows, or ``L"python3"`` on other
        platforms.

      Default: ``NULL``.

      Part of the :ref:`Python Path Configuration <init-path-config>` input.

   .. c:member:: wchar_t* pycache_prefix

      Directory where cached ``.pyc`` files are written:
      :data:`sys.pycache_prefix`.

      Set by the :option:`-X pycache_prefix=PATH <-X>` command line option and
      the :envvar:`PYTHONPYCACHEPREFIX` environment variable.

      If ``NULL``, :data:`sys.pycache_prefix` is set to ``None``.

      Default: ``NULL``.

   .. c:member:: int quiet

      Quiet mode. If greater than 0, don't display the copyright and version at
      Python startup in interactive mode.

      Incremented by the :option:`-q` command line option.

      Default: ``0``.

   .. c:member:: wchar_t* run_command

      Value of the :option:`-c` command line option.

      Used by :c:func:`Py_RunMain`.

      Default: ``NULL``.

   .. c:member:: wchar_t* run_filename

      Filename passed on the command line: trailing command line argument
      without :option:`-c` or :option:`-m`.

      For example, it is set to ``script.py`` by the ``python3 script.py arg``
      command.

      Used by :c:func:`Py_RunMain`.

      Default: ``NULL``.

   .. c:member:: wchar_t* run_module

      Value of the :option:`-m` command line option.

      Used by :c:func:`Py_RunMain`.

      Default: ``NULL``.

   .. c:member:: int show_ref_count

      Show total reference count at exit?

      Set to 1 by :option:`-X showrefcount <-X>` command line option.

      Need a :ref:`debug build of Python <debug-build>` (the ``Py_REF_DEBUG``
      macro must be defined).

      Default: ``0``.

   .. c:member:: int site_import

      Import the :mod:`site` module at startup?

      If equal to zero, disable the import of the module site and the
      site-dependent manipulations of :data:`sys.path` that it entails.

      Also disable these manipulations if the :mod:`site` module is explicitly
      imported later (call :func:`site.main` if you want them to be triggered).

      Set to ``0`` by the :option:`-S` command line option.

      :data:`sys.flags.no_site` is set to the inverted value of
      :c:member:`~PyConfig.site_import`.

      Default: ``1``.

   .. c:member:: int skip_source_first_line

      If non-zero, skip the first line of the :c:member:`PyConfig.run_filename`
      source.

      It allows the usage of non-Unix forms of ``#!cmd``. This is intended for
      a DOS specific hack only.

      Set to ``1`` by the :option:`-x` command line option.

      Default: ``0``.

   .. c:member:: wchar_t* stdio_encoding
   .. c:member:: wchar_t* stdio_errors

      Encoding and encoding errors of :data:`sys.stdin`, :data:`sys.stdout` and
      :data:`sys.stderr` (but :data:`sys.stderr` always uses
      ``"backslashreplace"`` error handler).

      If :c:func:`Py_SetStandardStreamEncoding` has been called, use its
      *error* and *errors* arguments if they are not ``NULL``.

      Use the :envvar:`PYTHONIOENCODING` environment variable if it is
      non-empty.

      Default encoding:

      * ``"UTF-8"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero.
      * Otherwise, use the :term:`locale encoding`.

      Default error handler:

      * On Windows: use ``"surrogateescape"``.
      * ``"surrogateescape"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero,
        or if the LC_CTYPE locale is "C" or "POSIX".
      * ``"strict"`` otherwise.

   .. c:member:: int tracemalloc

      Enable tracemalloc?

      If non-zero, call :func:`tracemalloc.start` at startup.

      Set by :option:`-X tracemalloc=N <-X>` command line option and by the
      :envvar:`PYTHONTRACEMALLOC` environment variable.

      Default: ``-1`` in Python mode, ``0`` in isolated mode.

   .. c:member:: int use_environment

      Use :ref:`environment variables <using-on-envvars>`?

      If equals to zero, ignore the :ref:`environment variables
      <using-on-envvars>`.

      Default: ``1`` in Python config and ``0`` in isolated config.

   .. c:member:: int user_site_directory

      If non-zero, add the user site directory to :data:`sys.path`.

      Set to ``0`` by the :option:`-s` and :option:`-I` command line options.

      Set to ``0`` by the :envvar:`PYTHONNOUSERSITE` environment variable.

      Default: ``1`` in Python mode, ``0`` in isolated mode.

   .. c:member:: int verbose

      Verbose mode. If greater than 0, print a message each time a module is
      imported, showing the place (filename or built-in module) from which
      it is loaded.

      If greater or equal to 2, print a message for each file that is checked
      for when searching for a module. Also provides information on module
      cleanup at exit.

      Incremented by the :option:`-v` command line option.

      Set to the :envvar:`PYTHONVERBOSE` environment variable value.

      Default: ``0``.

   .. c:member:: PyWideStringList warnoptions

      Options of the :mod:`warnings` module to build warnings filters, lowest
      to highest priority: :data:`sys.warnoptions`.

      The :mod:`warnings` module adds :data:`sys.warnoptions` in the reverse
      order: the last :c:member:`PyConfig.warnoptions` item becomes the first
      item of :data:`warnings.filters` which is checked first (highest
      priority).

      The :option:`-W` command line options adds its value to
      :c:member:`~PyConfig.warnoptions`, it can be used multiple times.

      The :envvar:`PYTHONWARNINGS` environment variable can also be used to add
      warning options. Multiple options can be specified, separated by commas
      (``,``).

      Default: empty list.

   .. c:member:: int write_bytecode

      If equal to 0, Python won't try to write ``.pyc`` files on the import of
      source modules.

      Set to ``0`` by the :option:`-B` command line option and the
      :envvar:`PYTHONDONTWRITEBYTECODE` environment variable.

      :data:`sys.dont_write_bytecode` is initialized to the inverted value of
      :c:member:`~PyConfig.write_bytecode`.

      Default: ``1``.

   .. c:member:: PyWideStringList xoptions

      Values of the :option:`-X` command line options: :data:`sys._xoptions`.

      Default: empty list.

If :c:member:`~PyConfig.parse_argv` is non-zero, :c:member:`~PyConfig.argv`
arguments are parsed the same way the regular Python parses :ref:`command line
arguments <using-on-cmdline>`, and Python arguments are stripped from
:c:member:`~PyConfig.argv`.

The :c:member:`~PyConfig.xoptions` options are parsed to set other options: see
the :option:`-X` command line option.

.. versionchanged:: 3.9

   The ``show_alloc_count`` field has been removed.


Initialization with PyConfig
============================

Function to initialize Python:

.. c:function:: PyStatus Py_InitializeFromConfig(const PyConfig *config)

   Initialize Python from *config* configuration.

The caller is responsible to handle exceptions (error or exit) using
:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.

If :c:func:`PyImport_FrozenModules`, :c:func:`PyImport_AppendInittab` or
:c:func:`PyImport_ExtendInittab` are used, they must be set or called after
Python preinitialization and before the Python initialization.

The current configuration (``PyConfig`` type) is stored in
``PyInterpreterState.config``.

Example setting the program name::

    void init_python(void)
    {
        PyStatus status;

        PyConfig config;
        PyConfig_InitPythonConfig(&config);

        /* Set the program name. Implicitly preinitialize Python. */
        status = PyConfig_SetString(&config, &config.program_name,
                                    L"/path/to/my_program");
        if (PyStatus_Exception(status)) {
            goto exception;
        }

        status = Py_InitializeFromConfig(&config);
        if (PyStatus_Exception(status)) {
            goto exception;
        }
        PyConfig_Clear(&config);
        return;

    exception:
        PyConfig_Clear(&config);
        Py_ExitStatusException(status);
    }

More complete example modifying the default configuration, read the
configuration, and then override some parameters::

    PyStatus init_python(const char *program_name)
    {
        PyStatus status;

        PyConfig config;
        PyConfig_InitPythonConfig(&config);

        /* Set the program name before reading the configuration
           (decode byte string from the locale encoding).

           Implicitly preinitialize Python. */
        status = PyConfig_SetBytesString(&config, &config.program_name,
                                         program_name);
        if (PyStatus_Exception(status)) {
            goto done;
        }

        /* Read all configuration at once */
        status = PyConfig_Read(&config);
        if (PyStatus_Exception(status)) {
            goto done;
        }

        /* Append our custom search path to sys.path */
        status = PyWideStringList_Append(&config.module_search_paths,
                                         L"/path/to/more/modules");
        if (PyStatus_Exception(status)) {
            goto done;
        }

        /* Override executable computed by PyConfig_Read() */
        status = PyConfig_SetString(&config, &config.executable,
                                    L"/path/to/my_executable");
        if (PyStatus_Exception(status)) {
            goto done;
        }

        status = Py_InitializeFromConfig(&config);

    done:
        PyConfig_Clear(&config);
        return status;
    }


.. _init-isolated-conf:

Isolated Configuration
======================

:c:func:`PyPreConfig_InitIsolatedConfig` and
:c:func:`PyConfig_InitIsolatedConfig` functions create a configuration to
isolate Python from the system. For example, to embed Python into an
application.

This configuration ignores global configuration variables, environments
variables, command line arguments (:c:member:`PyConfig.argv` is not parsed)
and user site directory. The C standard streams (ex: ``stdout``) and the
LC_CTYPE locale are left unchanged. Signal handlers are not installed.

Configuration files are still used with this configuration. Set the
:ref:`Python Path Configuration <init-path-config>` ("output fields") to ignore these
configuration files and avoid the function computing the default path
configuration.


.. _init-python-config:

Python Configuration
====================

:c:func:`PyPreConfig_InitPythonConfig` and :c:func:`PyConfig_InitPythonConfig`
functions create a configuration to build a customized Python which behaves as
the regular Python.

Environments variables and command line arguments are used to configure
Python, whereas global configuration variables are ignored.

This function enables C locale coercion (:pep:`538`)
and :ref:`Python UTF-8 Mode <utf8-mode>`
(:pep:`540`) depending on the LC_CTYPE locale, :envvar:`PYTHONUTF8` and
:envvar:`PYTHONCOERCECLOCALE` environment variables.


.. _init-path-config:

Python Path Configuration
=========================

:c:type:`PyConfig` contains multiple fields for the path configuration:

* Path configuration inputs:

  * :c:member:`PyConfig.home`
  * :c:member:`PyConfig.platlibdir`
  * :c:member:`PyConfig.pathconfig_warnings`
  * :c:member:`PyConfig.program_name`
  * :c:member:`PyConfig.pythonpath_env`
  * current working directory: to get absolute paths
  * ``PATH`` environment variable to get the program full path
    (from :c:member:`PyConfig.program_name`)
  * ``__PYVENV_LAUNCHER__`` environment variable
  * (Windows only) Application paths in the registry under
    "Software\Python\PythonCore\X.Y\PythonPath" of HKEY_CURRENT_USER and
    HKEY_LOCAL_MACHINE (where X.Y is the Python version).

* Path configuration output fields:

  * :c:member:`PyConfig.base_exec_prefix`
  * :c:member:`PyConfig.base_executable`
  * :c:member:`PyConfig.base_prefix`
  * :c:member:`PyConfig.exec_prefix`
  * :c:member:`PyConfig.executable`
  * :c:member:`PyConfig.module_search_paths_set`,
    :c:member:`PyConfig.module_search_paths`
  * :c:member:`PyConfig.prefix`

If at least one "output field" is not set, Python calculates the path
configuration to fill unset fields. If
:c:member:`~PyConfig.module_search_paths_set` is equal to 0,
:c:member:`~PyConfig.module_search_paths` is overridden and
:c:member:`~PyConfig.module_search_paths_set` is set to 1.

It is possible to completely ignore the function calculating the default
path configuration by setting explicitly all path configuration output
fields listed above. A string is considered as set even if it is non-empty.
``module_search_paths`` is considered as set if
``module_search_paths_set`` is set to 1. In this case, path
configuration input fields are ignored as well.

Set :c:member:`~PyConfig.pathconfig_warnings` to 0 to suppress warnings when
calculating the path configuration (Unix only, Windows does not log any warning).

If :c:member:`~PyConfig.base_prefix` or :c:member:`~PyConfig.base_exec_prefix`
fields are not set, they inherit their value from :c:member:`~PyConfig.prefix`
and :c:member:`~PyConfig.exec_prefix` respectively.

:c:func:`Py_RunMain` and :c:func:`Py_Main` modify :data:`sys.path`:

* If :c:member:`~PyConfig.run_filename` is set and is a directory which contains a
  ``__main__.py`` script, prepend :c:member:`~PyConfig.run_filename` to
  :data:`sys.path`.
* If :c:member:`~PyConfig.isolated` is zero:

  * If :c:member:`~PyConfig.run_module` is set, prepend the current directory
    to :data:`sys.path`. Do nothing if the current directory cannot be read.
  * If :c:member:`~PyConfig.run_filename` is set, prepend the directory of the
    filename to :data:`sys.path`.
  * Otherwise, prepend an empty string to :data:`sys.path`.

If :c:member:`~PyConfig.site_import` is non-zero, :data:`sys.path` can be
modified by the :mod:`site` module. If
:c:member:`~PyConfig.user_site_directory` is non-zero and the user's
site-package directory exists, the :mod:`site` module appends the user's
site-package directory to :data:`sys.path`.

The following configuration files are used by the path configuration:

* ``pyvenv.cfg``
* ``python._pth`` (Windows only)
* ``pybuilddir.txt`` (Unix only)

The ``__PYVENV_LAUNCHER__`` environment variable is used to set
:c:member:`PyConfig.base_executable`


Py_RunMain()
============

.. c:function:: int Py_RunMain(void)

   Execute the command (:c:member:`PyConfig.run_command`), the script
   (:c:member:`PyConfig.run_filename`) or the module
   (:c:member:`PyConfig.run_module`) specified on the command line or in the
   configuration.

   By default and when if :option:`-i` option is used, run the REPL.

   Finally, finalizes Python and returns an exit status that can be passed to
   the ``exit()`` function.

See :ref:`Python Configuration <init-python-config>` for an example of
customized Python always running in isolated mode using
:c:func:`Py_RunMain`.


Py_GetArgcArgv()
================

.. c:function:: void Py_GetArgcArgv(int *argc, wchar_t ***argv)

   Get the original command line arguments, before Python modified them.

   See also :c:member:`PyConfig.orig_argv` member.


Multi-Phase Initialization Private Provisional API
==================================================

This section is a private provisional API introducing multi-phase
initialization, the core feature of the :pep:`432`:

* "Core" initialization phase, "bare minimum Python":

  * Builtin types;
  * Builtin exceptions;
  * Builtin and frozen modules;
  * The :mod:`sys` module is only partially initialized
    (ex: :data:`sys.path` doesn't exist yet).

* "Main" initialization phase, Python is fully initialized:

  * Install and configure :mod:`importlib`;
  * Apply the :ref:`Path Configuration <init-path-config>`;
  * Install signal handlers;
  * Finish :mod:`sys` module initialization (ex: create :data:`sys.stdout`
    and :data:`sys.path`);
  * Enable optional features like :mod:`faulthandler` and :mod:`tracemalloc`;
  * Import the :mod:`site` module;
  * etc.

Private provisional API:

* :c:member:`PyConfig._init_main`: if set to 0,
  :c:func:`Py_InitializeFromConfig` stops at the "Core" initialization phase.
* :c:member:`PyConfig._isolated_interpreter`: if non-zero,
  disallow threads, subprocesses and fork.

.. c:function:: PyStatus _Py_InitializeMain(void)

   Move to the "Main" initialization phase, finish the Python initialization.

No module is imported during the "Core" phase and the ``importlib`` module is
not configured: the :ref:`Path Configuration <init-path-config>` is only
applied during the "Main" phase. It may allow to customize Python in Python to
override or tune the :ref:`Path Configuration <init-path-config>`, maybe
install a custom :data:`sys.meta_path` importer or an import hook, etc.

It may become possible to calculatin the :ref:`Path Configuration
<init-path-config>` in Python, after the Core phase and before the Main phase,
which is one of the :pep:`432` motivation.

The "Core" phase is not properly defined: what should be and what should
not be available at this phase is not specified yet. The API is marked
as private and provisional: the API can be modified or even be removed
anytime until a proper public API is designed.

Example running Python code between "Core" and "Main" initialization
phases::

    void init_python(void)
    {
        PyStatus status;

        PyConfig config;
        PyConfig_InitPythonConfig(&config);
        config._init_main = 0;

        /* ... customize 'config' configuration ... */

        status = Py_InitializeFromConfig(&config);
        PyConfig_Clear(&config);
        if (PyStatus_Exception(status)) {
            Py_ExitStatusException(status);
        }

        /* Use sys.stderr because sys.stdout is only created
           by _Py_InitializeMain() */
        int res = PyRun_SimpleString(
            "import sys; "
            "print('Run Python code before _Py_InitializeMain', "
                   "file=sys.stderr)");
        if (res < 0) {
            exit(1);
        }

        /* ... put more configuration code here ... */

        status = _Py_InitializeMain();
        if (PyStatus_Exception(status)) {
            Py_ExitStatusException(status);
        }
    }