As specified in :pep:`11`, a Python release only supports a Windows platform
while Microsoft considers the platform under extended support. This means that
-Python 3.5 supports Windows Vista and newer. If you require Windows XP support
+Python 3.6 supports Windows Vista and newer. If you require Windows XP support
then please install Python 3.4.
Installation Steps
------------------
-Four Python 3.5 installers are available for download - two each for the 32-bit
+Four Python 3.6 installers are available for download - two each for the 32-bit
and 64-bit versions of the interpreter. The *web installer* is a small initial
download, and it will automatically download the required components as
necessary. The *offline installer* includes the components necessary for a
For example, to silently install a default, system-wide Python installation,
you could use the following command (from an elevated command prompt)::
- python-3.5.0.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0
+ python-3.6.0.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0
To allow users to easily install a personal copy of Python without the test
suite, you could provide a shortcut with the following command. This will
display a simplified initial page and disallow customization::
- python-3.5.0.exe InstallAllUsers=0 Include_launcher=0 Include_test=0
+ python-3.6.0.exe InstallAllUsers=0 Include_launcher=0 Include_test=0
SimpleInstall=1 SimpleInstallDescription="Just for me, no test suite."
(Note that omitting the launcher also omits file associations, and is only
useful to have a locally cached copy.
Execute the following command from Command Prompt to download all possible
-required files. Remember to substitute ``python-3.5.0.exe`` for the actual
+required files. Remember to substitute ``python-3.6.0.exe`` for the actual
name of your installer, and to create layouts in their own directories to
avoid collisions between files with the same name.
::
- python-3.5.0.exe /layout [optional target directory]
+ python-3.6.0.exe /layout [optional target directory]
You may also specify the ``/quiet`` option to hide the progress display.
To temporarily set environment variables, open Command Prompt and use the
:command:`set` command::
- C:\>set PATH=C:\Program Files\Python 3.5;%PATH%
+ C:\>set PATH=C:\Program Files\Python 3.6;%PATH%
C:\>set PYTHONPATH=%PYTHONPATH%;C:\My_python_lib
C:\>python
Besides using the automatically created start menu entry for the Python
interpreter, you might want to start Python in the command prompt. The
-installer for Python 3.5 and later has an option to set that up for you.
+installer for Python 3.6 has an option to set that up for you.
-On the first page of the installer, an option labelled "Add Python 3.5 to
-PATH" can be selected to have the installer add the install location into the
+On the first page of the installer, an option labelled "Add Python to PATH"
+may be selected to have the installer add the install location into the
:envvar:`PATH`. The location of the :file:`Scripts\\` folder is also added.
This allows you to type :command:`python` to run the interpreter, and
:command:`pip` for the package installer. Thus, you can also execute your
example variable could look like this (assuming the first two entries already
existed)::
- C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files\Python 3.5
+ C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files\Python 3.6
.. _launcher:
:file:`C:\\Python\\Lib\\` and third-party modules should be stored in
:file:`C:\\Python\\Lib\\site-packages\\`.
-This is how :data:`sys.path` is populated on Windows:
+To completely override :data:`sys.path`, create a text file named ``'sys.path'``
+containing a list of paths alongside the Python executable. This will ignore all
+registry settings and environment variables, enable isolated mode, disable
+importing :mod:`site`, and fill :data:`sys.path` with exactly the paths listed
+in the file. Paths may be absolute or relative to the directory containing the
+file.
+
+When the ``'sys.path'`` file is missing, this is how :data:`sys.path` is
+populated on Windows:
* An empty entry is added at the start, which corresponds to the current
directory.
path is used instead of the path to the main executable when deducing the
home location.
-* If ``applocal`` is set to true, the ``home`` property or the main executable
- is always used as the home path, and all environment variables or registry
- values affecting the path are ignored. The landmark file is not checked.
-
The end result of all this is:
* When running :file:`python.exe`, or any other .exe in the main Python
For those who want to bundle Python into their application or distribution, the
following advice will prevent conflicts with other installations:
-* Include a ``pyvenv.cfg`` file alongside your executable containing
- ``applocal = true``. This will ensure that your own directory will be used to
- resolve paths even if you have included the standard library in a ZIP file.
- It will also ignore user site-packages and other paths listed in the
- registry.
+* Include a ``sys.path`` file alongside your executable containing the
+ directories to include. This will ignore user site-packages and other paths
+ listed in the registry or in environment variables.
-* If you are loading :file:`python3.dll` or :file:`python35.dll` in your own
+* If you are loading :file:`python3.dll` or :file:`python36.dll` in your own
executable, explicitly call :c:func:`Py_SetPath` or (at least)
:c:func:`Py_SetProgramName` before :c:func:`Py_Initialize`.
the first suggestion is the best, as the other may still be susceptible to
non-standard paths in the registry and user site-packages.
+.. versionchanged:: 3.6
+
+ Adds ``sys.path`` file support and removes ``applocal`` option from
+ ``pyvenv.cfg``.
+
Additional modules
==================
When extracted, the embedded distribution is (almost) fully isolated from the
user's system, including environment variables, system registry settings, and
installed packages. The standard library is included as pre-compiled and
-optimized ``.pyc`` files in a ZIP, and ``python3.dll``, ``python35.dll``,
+optimized ``.pyc`` files in a ZIP, and ``python3.dll``, ``python36.dll``,
``python.exe`` and ``pythonw.exe`` are all provided. Tcl/tk (including all
dependants, such as Idle), pip and the Python documentation are not included.
PATH RULES FOR WINDOWS:
This describes how sys.path is formed on Windows. It describes the
functionality, not the implementation (ie, the order in which these
- are actually fetched is different)
+ are actually fetched is different). The presence of a sys.path file
+ alongside the program overrides these rules - see below.
* Python always adds an empty entry at the start, which corresponds
to the current directory.
used (eg. .\Lib;.\plat-win, etc)
+ If a sys.path file exists adjacent to python.exe, it must contain a
+ list of paths to add to sys.path, one per line (like a .pth file but without
+ the ability to execute arbitrary code). Each path is relative to the
+ directory containing the file. No other paths are added to the search path,
+ and the registry finder is not enabled.
+
The end result of all this is:
* When running python.exe, or any other .exe in the main Python directory
(either an installed version, or directly from the PCbuild directory),
some default, but relative, paths.
* An embedding application can use Py_SetPath() to override all of
- these authomatic path computations.
+ these automatic path computations.
+
+ * An isolation install of Python can disable all implicit paths by
+ providing a sys.path file.
---------------------------------------------------------------- */
#include "osdefs.h"
#include <wchar.h>
-#ifdef MS_WINDOWS
-#include <windows.h>
+#ifndef MS_WINDOWS
+#error getpathp.c should only be built on Windows
#endif
+#include <windows.h>
+#include <Shlwapi.h>
+
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
than MAXPATHLEN characters at exit. If stuff is too long, only as much of
stuff as fits will be appended.
*/
+
+static int _PathCchCombineEx_Initialized = 0;
+typedef HRESULT(__stdcall *PPathCchCombineEx)(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFlags);
+static PPathCchCombineEx _PathCchCombineEx;
+
static void
join(wchar_t *buffer, const wchar_t *stuff)
{
- size_t n;
- if (is_sep(stuff[0]) ||
- (wcsnlen_s(stuff, 4) >= 3 && stuff[1] == ':' && is_sep(stuff[2]))) {
- if (wcscpy_s(buffer, MAXPATHLEN+1, stuff) != 0)
- Py_FatalError("buffer overflow in getpathp.c's join()");
- return;
+ if (_PathCchCombineEx_Initialized == 0) {
+ HMODULE pathapi = LoadLibraryW(L"api-ms-win-core-path-l1-1-0.dll");
+ if (pathapi)
+ _PathCchCombineEx = (PPathCchCombineEx)GetProcAddress(pathapi, "PathCchCombineEx");
+ else
+ _PathCchCombineEx = NULL;
+ _PathCchCombineEx_Initialized = 1;
}
- n = wcsnlen_s(buffer, MAXPATHLEN+1);
- if (n > 0 && !is_sep(buffer[n - 1]) && n < MAXPATHLEN) {
- buffer[n] = SEP;
- buffer[n + 1] = '\0';
+ if (_PathCchCombineEx) {
+ if (FAILED(_PathCchCombineEx(buffer, MAXPATHLEN+1, buffer, stuff, 0)))
+ Py_FatalError("buffer overflow in getpathp.c's join()");
+ } else {
+ if (!PathCombineW(buffer, NULL, stuff))
+ Py_FatalError("buffer overflow in getpathp.c's join()");
}
- if (wcscat_s(buffer, MAXPATHLEN+1, stuff) != 0)
- Py_FatalError("buffer overflow in getpathp.c's join()");
}
/* gotlandmark only called by search_for_prefix, which ensures
return 0;
}
-#ifdef MS_WINDOWS
#ifdef Py_ENABLE_SHARED
/* a string loaded from the DLL at startup.*/
return retval;
}
#endif /* Py_ENABLE_SHARED */
-#endif /* MS_WINDOWS */
static void
get_progpath(void)
wchar_t *path = _wgetenv(L"PATH");
wchar_t *prog = Py_GetProgramName();
-#ifdef MS_WINDOWS
#ifdef Py_ENABLE_SHARED
extern HANDLE PyWin_DLLhModule;
/* static init of progpath ensures final char remains \0 */
#endif
if (GetModuleFileNameW(NULL, progpath, MAXPATHLEN))
return;
-#endif
if (prog == NULL || *prog == '\0')
prog = L"python";
return result;
}
+static int
+read_sys_path_file(const wchar_t *path, const wchar_t *prefix)
+{
+ FILE *sp_file = _Py_wfopen(path, L"r");
+ if (sp_file == NULL)
+ return -1;
+
+ size_t bufsiz = MAXPATHLEN;
+ size_t prefixlen = wcslen(prefix);
+
+ wchar_t *buf = (wchar_t*)PyMem_RawMalloc(bufsiz * sizeof(wchar_t));
+ buf[0] = '\0';
+
+ while (!feof(sp_file)) {
+ char line[MAXPATHLEN + 1];
+ char *p = fgets(line, MAXPATHLEN + 1, sp_file);
+ if (!p)
+ break;
+
+ DWORD n = strlen(line);
+ if (n == 0 || p[n - 1] != '\n')
+ break;
+ if (n > 2 && p[n - 1] == '\r')
+ --n;
+
+ DWORD wn = MultiByteToWideChar(CP_UTF8, 0, line, n - 1, NULL, 0);
+ wchar_t *wline = (wchar_t*)PyMem_RawMalloc((wn + 1) * sizeof(wchar_t));
+ wn = MultiByteToWideChar(CP_UTF8, 0, line, n - 1, wline, wn);
+ wline[wn] = '\0';
+
+ while (wn + prefixlen + 4 > bufsiz) {
+ bufsiz += MAXPATHLEN;
+ buf = (wchar_t*)PyMem_RawRealloc(buf, (bufsiz + 1) * sizeof(wchar_t));
+ if (!buf) {
+ PyMem_RawFree(wline);
+ goto error;
+ }
+ }
+
+ if (buf[0])
+ wcscat_s(buf, bufsiz, L";");
+ wchar_t *b = &buf[wcslen(buf)];
+
+ wcscat_s(buf, bufsiz, prefix);
+ join(b, wline);
+
+ PyMem_RawFree(wline);
+ }
+
+ module_search_path = buf;
+
+ fclose(sp_file);
+ return 0;
+
+error:
+ PyMem_RawFree(buf);
+ fclose(sp_file);
+ return -1;
+}
+
+
static void
calculate_path(void)
{
wchar_t *pythonhome = Py_GetPythonHome();
wchar_t *envpath = NULL;
-#ifdef MS_WINDOWS
int skiphome, skipdefault;
wchar_t *machinepath = NULL;
wchar_t *userpath = NULL;
wchar_t zip_path[MAXPATHLEN+1];
- int applocal = 0;
if (!Py_IgnoreEnvironmentFlag) {
envpath = _wgetenv(L"PYTHONPATH");
}
-#else
- char *_envpath = Py_GETENV("PYTHONPATH");
- wchar_t wenvpath[MAXPATHLEN+1];
- if (_envpath) {
- size_t r = mbstowcs(wenvpath, _envpath, MAXPATHLEN+1);
- envpath = wenvpath;
- if (r == (size_t)-1 || r >= MAXPATHLEN)
- envpath = NULL;
- }
-#endif
get_progpath();
/* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */
wcscpy_s(argv0_path, MAXPATHLEN+1, progpath);
reduce(argv0_path);
+ /* Search for a sys.path file */
+ {
+ wchar_t spbuffer[MAXPATHLEN+1];
+
+ wcscpy_s(spbuffer, MAXPATHLEN+1, argv0_path);
+ join(spbuffer, L"sys.path");
+ if (exists(spbuffer) && read_sys_path_file(spbuffer, argv0_path) == 0) {
+ wcscpy_s(prefix, MAXPATHLEN + 1, argv0_path);
+ Py_IsolatedFlag = 1;
+ Py_NoSiteFlag = 1;
+ return;
+ }
+ }
+
/* Search for an environment configuration file, first in the
executable's directory and then in the parent directory.
If found, open it for use when searching for prefixes.
}
}
if (env_file != NULL) {
- /* Look for an 'applocal' variable and, if true, ignore all registry
- * keys and environment variables, but retain the default paths
- * (DLLs, Lib) and the zip file. Setting pythonhome here suppresses
- * the search for LANDMARK below and overrides %PYTHONHOME%.
- */
- if (find_env_config_value(env_file, L"applocal", tmpbuffer) &&
- (applocal = (wcsicmp(tmpbuffer, L"true") == 0))) {
- envpath = NULL;
- pythonhome = argv0_path;
- }
-
/* Look for a 'home' variable and set argv0_path to it, if found */
if (find_env_config_value(env_file, L"home", tmpbuffer)) {
wcscpy_s(argv0_path, MAXPATHLEN+1, tmpbuffer);
envpath = NULL;
-#ifdef MS_WINDOWS
/* Calculate zip archive path from DLL or exe path */
if (wcscpy_s(zip_path, MAXPATHLEN+1, dllpath[0] ? dllpath : progpath))
/* exceeded buffer length - ignore zip_path */
skiphome = pythonhome==NULL ? 0 : 1;
#ifdef Py_ENABLE_SHARED
- if (!applocal) {
- machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome);
- userpath = getpythonregpath(HKEY_CURRENT_USER, skiphome);
- }
+ machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome);
+ userpath = getpythonregpath(HKEY_CURRENT_USER, skiphome);
#endif
/* We only use the default relative PYTHONPATH if we havent
anything better to use! */
skipdefault = envpath!=NULL || pythonhome!=NULL || \
machinepath!=NULL || userpath!=NULL;
-#endif
/* We need to construct a path from the following parts.
(1) the PYTHONPATH environment variable, if set;
Extra rules:
- If PYTHONHOME is set (in any way) item (3) is ignored.
- If registry values are used, (4) and (5) are ignored.
- - If applocal is set, (1), (3), and registry values are ignored
*/
/* Calculate size of return buffer */
bufsz = 0;
bufsz += wcslen(PYTHONPATH) + 1;
bufsz += wcslen(argv0_path) + 1;
-#ifdef MS_WINDOWS
- if (!applocal && userpath)
+ if (userpath)
bufsz += wcslen(userpath) + 1;
- if (!applocal && machinepath)
+ if (machinepath)
bufsz += wcslen(machinepath) + 1;
bufsz += wcslen(zip_path) + 1;
-#endif
if (envpath != NULL)
bufsz += wcslen(envpath) + 1;
fprintf(stderr, "Using default static path.\n");
module_search_path = PYTHONPATH;
}
-#ifdef MS_WINDOWS
PyMem_RawFree(machinepath);
PyMem_RawFree(userpath);
-#endif /* MS_WINDOWS */
return;
}
buf = wcschr(buf, L'\0');
*buf++ = DELIM;
}
-#ifdef MS_WINDOWS
if (zip_path[0]) {
if (wcscpy_s(buf, bufsz - (buf - module_search_path), zip_path))
Py_FatalError("buffer overflow in getpathp.c's calculate_path()");
buf = wcschr(buf, L'\0');
*buf++ = DELIM;
}
- }
-#else
- if (pythonhome == NULL) {
- wcscpy(buf, PYTHONPATH);
- buf = wcschr(buf, L'\0');
- *buf++ = DELIM;
- }
-#endif /* MS_WINDOWS */
- else {
+ } else {
wchar_t *p = PYTHONPATH;
wchar_t *q;
size_t n;