* On VxWorks, os.popen, os.fork, os.execv and os.spawn*p* are not supported.
-* On WebAssembly platforms ``wasm32-emscripten`` and ``wasm32-wasi``, large
- parts of the :mod:`os` module are not available or behave differently. API
- related to processes (e.g. :func:`~os.fork`, :func:`~os.execve`), signals
- (e.g. :func:`~os.kill`, :func:`~os.wait`), and resources
- (e.g. :func:`~os.nice`) are not available. Others like :func:`~os.getuid`
- and :func:`~os.getpid` are emulated or stubs.
+* On WebAssembly platforms, and on iOS, large parts of the :mod:`os` module are
+ not available or behave differently. API related to processes (e.g.
+ :func:`~os.fork`, :func:`~os.execve`) and resources (e.g. :func:`~os.nice`)
+ are not available. Others like :func:`~os.getuid` and :func:`~os.getpid` are
+ emulated or stubs. WebAssembly platforms also lack support for signals (e.g.
+ :func:`~os.kill`, :func:`~os.wait`).
.. note::
Return the filename corresponding to the controlling terminal of the process.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: environ
Return the effective group id of the current process. This corresponds to the
"set id" bit on the file being executed in the current process.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: geteuid()
Return the current process's effective user id.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: getgid()
.. availability:: Unix.
- The function is a stub on Emscripten and WASI, see
- :ref:`wasm-availability` for more information.
+ The function is a stub on WASI, see :ref:`wasm-availability` for more
+ information.
.. function:: getgrouplist(user, group, /)
field from the password record for *user*, because that group ID will
otherwise be potentially omitted.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.3
Return list of supplemental group ids associated with the current process.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. note::
falls back to ``pwd.getpwuid(os.getuid())[0]`` to get the login name of the
current real user id.
- .. availability:: Unix, Windows, not Emscripten, not WASI.
+ .. availability:: Unix, Windows, not WASI.
.. function:: getpgid(pid)
Return the process group id of the process with process id *pid*. If *pid* is 0,
the process group id of the current process is returned.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: getpgrp()
Return the id of the current process group.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: getpid()
Return the current process id.
- The function is a stub on Emscripten and WASI, see
- :ref:`wasm-availability` for more information.
+ The function is a stub on WASI, see :ref:`wasm-availability` for more
+ information.
.. function:: getppid()
the id returned is the one of the init process (1), on Windows it is still
the same id, which may be already reused by another process.
- .. availability:: Unix, Windows, not Emscripten, not WASI.
+ .. availability:: Unix, Windows, not WASI.
.. versionchanged:: 3.2
Added support for Windows.
(respectively) the calling process, the process group of the calling process,
or the real user ID of the calling process.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.3
Parameters for the :func:`getpriority` and :func:`setpriority` functions.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.3
Return a tuple (ruid, euid, suid) denoting the current process's
real, effective, and saved user ids.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.2
Return a tuple (rgid, egid, sgid) denoting the current process's
real, effective, and saved group ids.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.2
.. availability:: Unix.
- The function is a stub on Emscripten and WASI, see
- :ref:`wasm-availability` for more information.
+ The function is a stub on WASI, see :ref:`wasm-availability` for more
+ information.
.. function:: initgroups(username, gid, /)
the groups of which the specified username is a member, plus the specified
group id.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.2
Set the current process's effective group id.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: seteuid(euid, /)
Set the current process's effective user id.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: setgid(gid, /)
Set the current process' group id.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: setgroups(groups, /)
*groups*. *groups* must be a sequence, and each element must be an integer
identifying a group. This operation is typically available only to the superuser.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. note:: On macOS, the length of *groups* may not exceed the
system-defined maximum number of effective group ids, typically 16.
Call the system call :c:func:`!setpgrp` or ``setpgrp(0, 0)`` depending on
which version is implemented (if any). See the Unix manual for the semantics.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: setpgid(pid, pgrp, /)
process with id *pid* to the process group with id *pgrp*. See the Unix manual
for the semantics.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: setpriority(which, who, priority)
*priority* is a value in the range -20 to 19. The default priority is 0;
lower priorities cause more favorable scheduling.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.3
Set the current process's real and effective group ids.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: setresgid(rgid, egid, sgid, /)
Set the current process's real, effective, and saved group ids.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.2
Set the current process's real, effective, and saved user ids.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.2
Set the current process's real and effective user ids.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: getsid(pid, /)
Call the system call :c:func:`!getsid`. See the Unix manual for the semantics.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: setsid()
Call the system call :c:func:`!setsid`. See the Unix manual for the semantics.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: setuid(uid, /)
Set the current process's user id.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. placed in this section since it relates to errno.... a little weak
Set the current numeric umask and return the previous umask.
- The function is a stub on Emscripten and WASI, see
- :ref:`wasm-availability` for more information.
+ The function is a stub on WASI, see :ref:`wasm-availability` for more
+ information.
.. function:: uname()
.. availability:: Unix, Windows.
- The function is limited on Emscripten and WASI, see
- :ref:`wasm-availability` for more information.
+ The function is limited on WASI, see :ref:`wasm-availability` for more
+ information.
.. versionchanged:: 3.13
Added support on Windows.
.. availability:: Unix.
- The function is limited on Emscripten and WASI, see
- :ref:`wasm-availability` for more information.
+ The function is limited on WASI, see :ref:`wasm-availability` for more
+ information.
.. function:: fdatasync(fd)
.. availability:: Unix, Windows.
- The function is limited on Emscripten and WASI, see
- :ref:`wasm-availability` for more information.
+ The function is limited on WASI, see :ref:`wasm-availability` for more
+ information.
On Windows, this function is limited to pipes.
Calls the C standard library function :c:func:`grantpt`.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.13
Make the calling process a session leader; make the tty the controlling tty,
the stdin, the stdout, and the stderr of the calling process; close fd.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.11
descriptors are :ref:`non-inheritable <fd_inheritance>`. For a (slightly) more
portable approach, use the :mod:`pty` module.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionchanged:: 3.4
The new file descriptors are now non-inheritable.
Return a pair of file descriptors ``(r, w)`` usable for reading and writing,
respectively.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.3
Ensures that enough disk space is allocated for the file specified by *fd*
starting from *offset* and continuing for *len* bytes.
- .. availability:: Unix, not Emscripten.
+ .. availability:: Unix.
.. versionadded:: 3.3
If the value :data:`O_CLOEXEC` is available on the system, it is added to
*oflag*.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.13
it is available; otherwise, the C standard library function
:c:func:`ptsname`, which is not guaranteed to be thread-safe, is called.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.13
Cross-platform applications should not use *headers*, *trailers* and *flags*
arguments.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. note::
Parameters to the :func:`sendfile` function, if the implementation supports
them.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.3
Parameter to the :func:`sendfile` function, if the implementation supports
it. The data won't be cached in the virtual memory and will be freed afterwards.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.11
.. availability:: Unix, Windows.
- The function is limited on Emscripten and WASI, see
- :ref:`wasm-availability` for more information.
+ The function is limited on WASI, see :ref:`wasm-availability` for more
+ information.
On Windows, this function is limited to pipes.
Calls the C standard library function :c:func:`unlockpt`.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionadded:: 3.13
streams are closed, and inheritable handles are only inherited if the
*close_fds* parameter is ``False``.
-On WebAssembly platforms ``wasm32-emscripten`` and ``wasm32-wasi``, the file
-descriptor cannot be modified.
+On WebAssembly platforms, the file descriptor cannot be modified.
.. function:: get_inheritable(fd, /)
.. audit-event:: os.chflags path,flags os.chflags
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionchanged:: 3.3
Added the *follow_symlinks* parameter.
constants or a corresponding integer value). All other bits are ignored.
The default value of *follow_symlinks* is ``False`` on Windows.
- The function is limited on Emscripten and WASI, see
- :ref:`wasm-availability` for more information.
+ The function is limited on WASI, see :ref:`wasm-availability` for more
+ information.
.. audit-event:: os.chmod path,mode,dir_fd os.chmod
.. availability:: Unix.
- The function is limited on Emscripten and WASI, see
- :ref:`wasm-availability` for more information.
+ The function is limited on WASI, see :ref:`wasm-availability` for more
+ information.
.. versionadded:: 3.3
Added support for specifying *path* as an open file descriptor,
Change the root directory of the current process to *path*.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionchanged:: 3.6
Accepts a :term:`path-like object`.
.. audit-event:: os.chflags path,flags os.lchflags
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionchanged:: 3.6
Accepts a :term:`path-like object`.
.. audit-event:: os.link src,dst,src_dir_fd,dst_dir_fd os.link
- .. availability:: Unix, Windows, not Emscripten.
+ .. availability:: Unix, Windows.
.. versionchanged:: 3.2
Added Windows support.
FIFO for reading, and the client opens it for writing. Note that :func:`mkfifo`
doesn't open the FIFO --- it just creates the rendezvous point.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionchanged:: 3.3
Added the *dir_fd* parameter.
This function can also support :ref:`paths relative to directory descriptors
<dir_fd>`.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. versionchanged:: 3.3
Added the *dir_fd* parameter.
.. availability:: Unix, Windows.
- The function is limited on Emscripten and WASI, see
- :ref:`wasm-availability` for more information.
+ The function is limited on WASI, see :ref:`wasm-availability` for more
+ information.
.. versionchanged:: 3.2
Added support for Windows 6.0 (Vista) symbolic links.
.. audit-event:: os.exec path,args,env os.execl
- .. availability:: Unix, Windows, not Emscripten, not WASI.
+ .. availability:: Unix, Windows, not WASI, not iOS.
.. versionchanged:: 3.3
Added support for specifying *path* as an open file descriptor
Exit code that means the command was used incorrectly, such as when the wrong
number of arguments are given.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_DATAERR
Exit code that means the input data was incorrect.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_NOINPUT
Exit code that means an input file did not exist or was not readable.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_NOUSER
Exit code that means a specified user did not exist.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_NOHOST
Exit code that means a specified host did not exist.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_UNAVAILABLE
Exit code that means that a required service is unavailable.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_SOFTWARE
Exit code that means an internal software error was detected.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_OSERR
Exit code that means an operating system error was detected, such as the
inability to fork or create a pipe.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_OSFILE
Exit code that means some system file did not exist, could not be opened, or had
some other kind of error.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_CANTCREAT
Exit code that means a user specified output file could not be created.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_IOERR
Exit code that means that an error occurred while doing I/O on some file.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_TEMPFAIL
that may not really be an error, such as a network connection that couldn't be
made during a retryable operation.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_PROTOCOL
Exit code that means that a protocol exchange was illegal, invalid, or not
understood.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_NOPERM
Exit code that means that there were insufficient permissions to perform the
operation (but not intended for file system problems).
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_CONFIG
Exit code that means that some kind of configuration error occurred.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. data:: EX_NOTFOUND
Exit code that means something like "an entry was not found".
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: fork()
for technical details of why we're surfacing this longstanding
platform compatibility problem to developers.
- .. availability:: POSIX, not Emscripten, not WASI.
+ .. availability:: POSIX, not WASI, not iOS.
.. function:: forkpty()
threads, this now raises a :exc:`DeprecationWarning`. See the
longer explanation on :func:`os.fork`.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: kill(pid, sig, /)
.. audit-event:: os.kill pid,sig os.kill
- .. availability:: Unix, Windows, not Emscripten, not WASI.
+ .. availability:: Unix, Windows, not WASI, not iOS.
.. versionchanged:: 3.2
Added Windows support.
.. audit-event:: os.killpg pgid,sig os.killpg
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: nice(increment, /)
Add *increment* to the process's "niceness". Return the new niceness.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI.
.. function:: pidfd_open(pid, flags=0)
Lock program segments into memory. The value of *op* (defined in
``<sys/lock.h>``) determines which segments are locked.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: popen(cmd, mode='r', buffering=-1)
documentation for more powerful ways to manage and communicate with
subprocesses.
- .. availability:: not Emscripten, not WASI.
+ .. availability:: not WASI, not iOS.
.. note::
The :ref:`Python UTF-8 Mode <utf8-mode>` affects encodings used
``os.POSIX_SPAWN_CLOSEFROM`` is available on platforms where
:c:func:`!posix_spawn_file_actions_addclosefrom_np` exists.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: posix_spawnp(path, argv, env, *, file_actions=None, \
setpgroup=None, resetids=False, setsid=False, setsigmask=(), \
.. versionadded:: 3.8
- .. availability:: POSIX, not Emscripten, not WASI.
+ .. availability:: POSIX, not WASI, not iOS.
See :func:`posix_spawn` documentation.
There is no way to unregister a function.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. versionadded:: 3.7
.. audit-event:: os.spawn mode,path,args,env os.spawnl
- .. availability:: Unix, Windows, not Emscripten, not WASI.
+ .. availability:: Unix, Windows, not WASI, not iOS.
:func:`spawnlp`, :func:`spawnlpe`, :func:`spawnvp`
and :func:`spawnvpe` are not available on Windows. :func:`spawnle` and
.. audit-event:: os.system command os.system
- .. availability:: Unix, Windows, not Emscripten, not WASI.
+ .. availability:: Unix, Windows, not WASI, not iOS.
.. function:: times()
:func:`waitstatus_to_exitcode` can be used to convert the exit status into an
exit code.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. seealso::
Otherwise, if there are no matching children
that could be waited for, :exc:`ChildProcessError` is raised.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. versionadded:: 3.3
:func:`waitstatus_to_exitcode` can be used to convert the exit status into an
exit code.
- .. availability:: Unix, Windows, not Emscripten, not WASI.
+ .. availability:: Unix, Windows, not WASI, not iOS.
.. versionchanged:: 3.5
If the system call is interrupted and the signal handler does not raise an
:func:`waitstatus_to_exitcode` can be used to convert the exit status into an
exitcode.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: wait4(pid, options)
:func:`waitstatus_to_exitcode` can be used to convert the exit status into an
exitcode.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. data:: P_PID
* :data:`!P_PIDFD` - wait for the child identified by the file descriptor
*id* (a process file descriptor created with :func:`pidfd_open`).
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. note:: :data:`!P_PIDFD` is only available on Linux >= 5.4.
:func:`waitid` causes child processes to be reported if they have been
continued from a job control stop since they were last reported.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. data:: WEXITED
The other ``wait*`` functions always report children that have terminated,
so this option is not available for them.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. versionadded:: 3.3
This option is not available for the other ``wait*`` functions.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. versionadded:: 3.3
This option is not available for :func:`waitid`.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. data:: WNOHANG
:func:`waitid` to return right away if no child process status is available
immediately.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. data:: WNOWAIT
This option is not available for the other ``wait*`` functions.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. data:: CLD_EXITED
These are the possible values for :attr:`!si_code` in the result returned by
:func:`waitid`.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. versionadded:: 3.3
:func:`WIFEXITED`, :func:`WEXITSTATUS`, :func:`WIFSIGNALED`,
:func:`WTERMSIG`, :func:`WIFSTOPPED`, :func:`WSTOPSIG` functions.
- .. availability:: Unix, Windows, not Emscripten, not WASI.
+ .. availability:: Unix, Windows, not WASI, not iOS.
.. versionadded:: 3.9
This function should be employed only if :func:`WIFSIGNALED` is true.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: WIFCONTINUED(status)
See :data:`WCONTINUED` option.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: WIFSTOPPED(status)
done using :data:`WUNTRACED` option or when the process is being traced (see
:manpage:`ptrace(2)`).
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: WIFSIGNALED(status)
Return ``True`` if the process was terminated by a signal, otherwise return
``False``.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: WIFEXITED(status)
by calling ``exit()`` or ``_exit()``, or by returning from ``main()``;
otherwise return ``False``.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: WEXITSTATUS(status)
This function should be employed only if :func:`WIFEXITED` is true.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: WSTOPSIG(status)
This function should be employed only if :func:`WIFSTOPPED` is true.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
.. function:: WTERMSIG(status)
This function should be employed only if :func:`WIFSIGNALED` is true.
- .. availability:: Unix, not Emscripten, not WASI.
+ .. availability:: Unix, not WASI, not iOS.
Interface to the scheduler
--- /dev/null
+.. _using-ios:
+
+===================
+Using Python on iOS
+===================
+
+:Authors:
+ Russell Keith-Magee (2024-03)
+
+Python on iOS is unlike Python on desktop platforms. On a desktop platform,
+Python is generally installed as a system resource that can be used by any user
+of that computer. Users then interact with Python by running a :program:`python`
+executable and entering commands at an interactive prompt, or by running a
+Python script.
+
+On iOS, there is no concept of installing as a system resource. The only unit
+of software distribution is an "app". There is also no console where you could
+run a :program:`python` executable, or interact with a Python REPL.
+
+As a result, the only way you can use Python on iOS is in embedded mode - that
+is, by writing a native iOS application, and embedding a Python interpreter
+using ``libPython``, and invoking Python code using the :ref:`Python embedding
+API <embedding>`. The full Python interpreter, the standard library, and all
+your Python code is then packaged as a standalone bundle that can be
+distributed via the iOS App Store.
+
+If you're looking to experiment for the first time with writing an iOS app in
+Python, projects such as `BeeWare <https://beeware.org>`__ and `Kivy
+<https://kivy.org>`__ will provide a much more approachable user experience.
+These projects manage the complexities associated with getting an iOS project
+running, so you only need to deal with the Python code itself.
+
+Python at runtime on iOS
+========================
+
+Platform identification
+-----------------------
+
+When executing on iOS, ``sys.platform`` will report as ``ios``. This value will
+be returned on an iPhone or iPad, regardless of whether the app is running on
+the simulator or a physical device.
+
+Information about the specific runtime environment, including the iOS version,
+device model, and whether the device is a simulator, can be obtained using
+:func:`platform.ios_ver()`. :func:`platform.system()` will report ``iOS`` or
+``iPadOS``, depending on the device.
+
+:func:`os.uname()` reports kernel-level details; it will report a name of
+``Darwin``.
+
+Standard library availability
+-----------------------------
+
+The Python standard library has some notable omissions and restrictions on
+iOS. See the :ref:`API availability guide for iOS <iOS-availability>` for
+details.
+
+Binary extension modules
+------------------------
+
+One notable difference about iOS as a platform is that App Store distribution
+imposes hard requirements on the packaging of an application. One of these
+requirements governs how binary extension modules are distributed.
+
+The iOS App Store requires that *all* binary modules in an iOS app must be
+dynamic libraries, contained in a framework with appropriate metadata, stored
+in the ``Frameworks`` folder of the packaged app. There can be only a single
+binary per framework, and there can be no executable binary material outside
+the ``Frameworks`` folder.
+
+This conflicts with the usual Python approach for distributing binaries, which
+allows a binary extension module to be loaded from any location on
+``sys.path``. To ensure compliance with App Store policies, an iOS project must
+post-process any Python packages, converting ``.so`` binary modules into
+individual standalone frameworks with appropriate metadata and signing. For
+details on how to perform this post-processing, see the guide for :ref:`adding
+Python to your project <adding-ios>`.
+
+To help Python discover binaries in their new location, the original ``.so``
+file on ``sys.path`` is replaced with a ``.fwork`` file. This file is a text
+file containing the location of the framework binary, relative to the app
+bundle. To allow the framework to resolve back to the original location, the
+framework must contain a ``.origin`` file that contains the location of the
+``.fwork`` file, relative to the app bundle.
+
+For example, consider the case of an import ``from foo.bar import _whiz``,
+where ``_whiz`` is implemented with the binary module
+``sources/foo/bar/_whiz.abi3.so``, with ``sources`` being the location
+registered on ``sys.path``, relative to the application bundle. This module
+*must* be distributed as ``Frameworks/foo.bar._whiz.framework/foo.bar._whiz``
+(creating the framework name from the full import path of the module), with an
+``Info.plist`` file in the ``.framework`` directory identifying the binary as a
+framework. The ``foo.bar._whiz`` module would be represented in the original
+location with a ``sources/foo/bar/_whiz.abi3.fwork`` marker file, containing
+the path ``Frameworks/foo.bar._whiz/foo.bar._whiz``. The framework would also
+contain ``Frameworks/foo.bar._whiz.framework/foo.bar._whiz.origin``, containing
+the path to the ``.fwork`` file.
+
+When running on iOS, the Python interpreter will install an
+:class:`~importlib.machinery.AppleFrameworkLoader` that is able to read and
+import ``.fwork`` files. Once imported, the ``__file__`` attribute of the
+binary module will report as the location of the ``.fwork`` file. However, the
+:class:`~importlib.machinery.ModuleSpec` for the loaded module will report the
+``origin`` as the location of the binary in the framework folder.
+
+Compiler stub binaries
+----------------------
+
+Xcode doesn't expose explicit compilers for iOS; instead, it uses an ``xcrun``
+script that resolves to a full compiler path (e.g., ``xcrun --sdk iphoneos
+clang`` to get the ``clang`` for an iPhone device). However, using this script
+poses two problems:
+
+* The output of ``xcrun`` includes paths that are machine specific, resulting
+ in a sysconfig module that cannot be shared between users; and
+
+* It results in ``CC``/``CPP``/``LD``/``AR`` definitions that include spaces.
+ There is a lot of C ecosystem tooling that assumes that you can split a
+ command line at the first space to get the path to the compiler executable;
+ this isn't the case when using ``xcrun``.
+
+To avoid these problems, Python provided stubs for these tools. These stubs are
+shell script wrappers around the underingly ``xcrun`` tools, distributed in a
+``bin`` folder distributed alongside the compiled iOS framework. These scripts
+are relocatable, and will always resolve to the appropriate local system paths.
+By including these scripts in the bin folder that accompanies a framework, the
+contents of the ``sysconfig`` module becomes useful for end-users to compile
+their own modules. When compiling third-party Python modules for iOS, you
+should ensure these stub binaries are on your path.
+
+Installing Python on iOS
+========================
+
+Tools for building iOS apps
+---------------------------
+
+Building for iOS requires the use of Apple's Xcode tooling. It is strongly
+recommended that you use the most recent stable release of Xcode. This will
+require the use of the most (or second-most) recently released macOS version,
+as Apple does not maintain Xcode for older macOS versions. The Xcode Command
+Line Tools are not sufficient for iOS development; you need a *full* Xcode
+install.
+
+If you want to run your code on the iOS simulator, you'll also need to install
+an iOS Simulator Platform. You should be prompted to select an iOS Simulator
+Platform when you first run Xcode. Alternatively, you can add an iOS Simulator
+Platform by selecting from the Platforms tab of the Xcode Settings panel.
+
+.. _adding-ios:
+
+Adding Python to an iOS project
+-------------------------------
+
+Python can be added to any iOS project, using either Swift or Objective C. The
+following examples will use Objective C; if you are using Swift, you may find a
+library like `PythonKit <https://github.com/pvieito/PythonKit>`__ to be
+helpful.
+
+To add Python to an iOS Xcode project:
+
+1. Build or obtain a Python ``XCFramework``. See the instructions in
+ :source:`iOS/README.rst` (in the CPython source distribution) for details on
+ how to build a Python ``XCFramework``. At a minimum, you will need a build
+ that supports ``arm64-apple-ios``, plus one of either
+ ``arm64-apple-ios-simulator`` or ``x86_64-apple-ios-simulator``.
+
+2. Drag the ``XCframework`` into your iOS project. In the following
+ instructions, we'll assume you've dropped the ``XCframework`` into the root
+ of your project; however, you can use any other location that you want by
+ adjusting paths as needed.
+
+3. Drag the ``iOS/Resources/dylib-Info-template.plist`` file into your project,
+ and ensure it is associated with the app target.
+
+4. Add your application code as a folder in your Xcode project. In the
+ following instructions, we'll assume that your user code is in a folder
+ named ``app`` in the root of your project; you can use any other location by
+ adjusting paths as needed. Ensure that this folder is associated with your
+ app target.
+
+5. Select the app target by selecting the root node of your Xcode project, then
+ the target name in the sidebar that appears.
+
+6. In the "General" settings, under "Frameworks, Libraries and Embedded
+ Content", add ``Python.xcframework``, with "Embed & Sign" selected.
+
+7. In the "Build Settings" tab, modify the following:
+
+ - Build Options
+
+ * User Script Sandboxing: No
+ * Enable Testability: Yes
+
+ - Search Paths
+
+ * Framework Search Paths: ``$(PROJECT_DIR)``
+ * Header Search Paths: ``"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers"``
+
+ - Apple Clang - Warnings - All languages
+
+ * Quoted Include In Framework Header: No
+
+8. Add a build step that copies the Python standard library into your app. In
+ the "Build Phases" tab, add a new "Run Script" build step *before* the
+ "Embed Frameworks" step, but *after* the "Copy Bundle Resources" step. Name
+ the step "Install Target Specific Python Standard Library", disable the
+ "Based on dependency analysis" checkbox, and set the script content to:
+
+ .. code-block:: bash
+
+ set -e
+
+ mkdir -p "$CODESIGNING_FOLDER_PATH/python/lib"
+ if [ "$EFFECTIVE_PLATFORM_NAME" = "-iphonesimulator" ]; then
+ echo "Installing Python modules for iOS Simulator"
+ rsync -au --delete "$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-simulator/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/"
+ else
+ echo "Installing Python modules for iOS Device"
+ rsync -au --delete "$PROJECT_DIR/Python.xcframework/ios-arm64/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/"
+ fi
+
+ Note that the name of the simulator "slice" in the XCframework may be
+ different, depending the CPU architectures your ``XCFramework`` supports.
+
+9. Add a second build step that processes the binary extension modules in the
+ standard library into "Framework" format. Add a "Run Script" build step
+ *directly after* the one you added in step 8, named "Prepare Python Binary
+ Modules". It should also have "Based on dependency analysis" unchecked, with
+ the following script content:
+
+ .. code-block:: bash
+
+ set -e
+
+ install_dylib () {
+ INSTALL_BASE=$1
+ FULL_EXT=$2
+
+ # The name of the extension file
+ EXT=$(basename "$FULL_EXT")
+ # The location of the extension file, relative to the bundle
+ RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/}
+ # The path to the extension file, relative to the install base
+ PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/}
+ # The full dotted name of the extension module, constructed from the file path.
+ FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d "." -f 1 | tr "/" ".");
+ # A bundle identifier; not actually used, but required by Xcode framework packaging
+ FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr "_" "-")
+ # The name of the framework folder.
+ FRAMEWORK_FOLDER="Frameworks/$FULL_MODULE_NAME.framework"
+
+ # If the framework folder doesn't exist, create it.
+ if [ ! -d "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER" ]; then
+ echo "Creating framework for $RELATIVE_EXT"
+ mkdir -p "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER"
+ cp "$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist"
+ plutil -replace CFBundleExecutable -string "$FULL_MODULE_NAME" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist"
+ plutil -replace CFBundleIdentifier -string "$FRAMEWORK_BUNDLE_ID" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist"
+ fi
+
+ echo "Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME"
+ mv "$FULL_EXT" "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME"
+ # Create a placeholder .fwork file where the .so was
+ echo "$FRAMEWORK_FOLDER/$FULL_MODULE_NAME" > ${FULL_EXT%.so}.fwork
+ # Create a back reference to the .so file location in the framework
+ echo "${RELATIVE_EXT%.so}.fwork" > "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin"
+ }
+
+ PYTHON_VER=$(ls -1 "$CODESIGNING_FOLDER_PATH/python/lib")
+ echo "Install Python $PYTHON_VER standard library extension modules..."
+ find "$CODESIGNING_FOLDER_PATH/python/lib/$PYTHON_VER/lib-dynload" -name "*.so" | while read FULL_EXT; do
+ install_dylib python/lib/$PYTHON_VER/lib-dynload/ "$FULL_EXT"
+ done
+
+ # Clean up dylib template
+ rm -f "$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist"
+
+ echo "Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)..."
+ find "$CODESIGNING_FOLDER_PATH/Frameworks" -name "*.framework" -exec /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der "{}" \;
+
+10. Add Objective C code to initialize and use a Python interpreter in embedded
+ mode. You should ensure that:
+
+ * :c:member:`UTF-8 mode <PyPreConfig.utf8_mode>` is *enabled*;
+ * :c:member:`Buffered stdio <PyConfig.buffered_stdio>` is *disabled*;
+ * :c:member:`Writing bytecode <PyConfig.write_bytecode>` is *disabled*;
+ * :c:member:`Signal handlers <PyConfig.install_signal_handlers>` are *enabled*;
+ * ``PYTHONHOME`` for the interpreter is configured to point at the
+ ``python`` subfolder of your app's bundle; and
+ * The ``PYTHONPATH`` for the interpreter includes:
+
+ - the ``python/lib/python3.X`` subfolder of your app's bundle,
+ - the ``python/lib/python3.X/lib-dynload`` subfolder of your app's bundle, and
+ - the ``app`` subfolder of your app's bundle
+
+ Your app's bundle location can be determined using ``[[NSBundle mainBundle]
+ resourcePath]``.
+
+Steps 8, 9 and 10 of these instructions assume that you have a single folder of
+pure Python application code, named ``app``. If you have third-party binary
+modules in your app, some additional steps will be required:
+
+* You need to ensure that any folders containing third-party binaries are
+ either associated with the app target, or copied in as part of step 8. Step 8
+ should also purge any binaries that are not appropriate for the platform a
+ specific build is targetting (i.e., delete any device binaries if you're
+ building app app targeting the simulator).
+
+* Any folders that contain third-party binaries must be processed into
+ framework form by step 9. The invocation of ``install_dylib`` that processes
+ the ``lib-dynload`` folder can be copied and adapted for this purpose.
+
+* If you're using a separate folder for third-party packages, ensure that folder
+ is included as part of the ``PYTHONPATH`` configuration in step 10.