“Python/docs/3.9/faq/windows”的版本间差异
(autoload) |
小 (Page commit) |
||
第1行: | 第1行: | ||
+ | {{DISPLAYTITLE:Windows 上的 Python 常见问题解答 — Python 文档}} | ||
<div id="python-on-windows-faq" class="section"> | <div id="python-on-windows-faq" class="section"> | ||
<span id="windows-faq"></span> | <span id="windows-faq"></span> | ||
− | = | + | = Windows 上的 Python 常见问题解答 = |
− | <div id=" | + | <div id="contents" class="contents topic"> |
− | + | 内容 | |
− | * [[#python-on-windows-faq|Python | + | * [[#python-on-windows-faq|Windows 上的 Python 常见问题解答]] |
− | ** [[#how-do-i-run-a-python-program-under-windows| | + | ** [[#how-do-i-run-a-python-program-under-windows|如何在 Windows 下运行 Python 程序?]] |
− | ** [[#how-do-i-make-python-scripts-executable| | + | ** [[#how-do-i-make-python-scripts-executable|如何使 Python 脚本可执行?]] |
− | ** [[#why-does-python-sometimes-take-so-long-to-start| | + | ** [[#why-does-python-sometimes-take-so-long-to-start|为什么 Python 有时需要很长时间才能启动?]] |
− | ** [[#how-do-i-make-an-executable-from-a-python-script| | + | ** [[#how-do-i-make-an-executable-from-a-python-script|如何从 Python 脚本制作可执行文件?]] |
− | ** [[#is-a-pyd-file-the-same-as-a-dll| | + | ** [[#is-a-pyd-file-the-same-as-a-dll|<code>*.pyd</code> 文件与 DLL 相同吗?]] |
− | ** [[#how-can-i-embed-python-into-a-windows-application| | + | ** [[#how-can-i-embed-python-into-a-windows-application|如何将 Python 嵌入到 Windows 应用程序中?]] |
− | ** [[#how-do-i-keep-editors-from-inserting-tabs-into-my-python-source| | + | ** [[#how-do-i-keep-editors-from-inserting-tabs-into-my-python-source|如何防止编辑器将选项卡插入到我的 Python 源代码中?]] |
− | ** [[#how-do-i-check-for-a-keypress-without-blocking| | + | ** [[#how-do-i-check-for-a-keypress-without-blocking|如何在不阻塞的情况下检查按键?]] |
第23行: | 第24行: | ||
<span id="faq-run-program-under-windows"></span> | <span id="faq-run-program-under-windows"></span> | ||
− | == | + | == 如何在 Windows 下运行 Python 程序? == |
− | + | 这不一定是一个直截了当的问题。 如果您已经熟悉从 Windows 命令行运行程序,那么一切都将显而易见; 否则,您可能需要更多指导。 | |
− | |||
− | |||
− | + | 除非您使用某种集成开发环境,否则您最终将 ''将'' Windows 命令输入到各种称为“DOS 窗口”或“命令提示符窗口”的地方。 通常,您可以通过搜索 <code>cmd</code> 从搜索栏中创建这样的窗口。 您应该能够识别何时启动了这样的窗口,因为您会看到一个 Windows“命令提示符”,通常如下所示: | |
− | '' | ||
− | |||
− | |||
− | |||
− | |||
<div class="highlight-doscon notranslate"> | <div class="highlight-doscon notranslate"> | ||
第40行: | 第34行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="doscon">C:\></syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 这封信可能不同,后面可能还有其他内容,因此您可能很容易看到以下内容: | |
− | |||
<div class="highlight-doscon notranslate"> | <div class="highlight-doscon notranslate"> | ||
第52行: | 第45行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="doscon">D:\YourName\Projects\Python></syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 取决于您的计算机是如何设置的以及您最近对它做了什么。 一旦您启动了这样一个窗口,您就可以很好地运行 Python 程序了。 | |
− | |||
− | |||
− | + | 您需要意识到您的 Python 脚本必须由另一个名为 Python ''解释器'' 的程序处理。 解释器读取您的脚本,将其编译为字节码,然后执行字节码以运行您的程序。 那么,你如何安排解释器来处理你的 Python? | |
− | |||
− | |||
− | |||
− | + | 首先,您需要确保您的命令窗口将单词“py”识别为启动解释器的指令。 如果您打开了命令窗口,您应该尝试输入命令 <code>py</code> 并按回车键: | |
− | |||
− | |||
− | |||
<div class="highlight-doscon notranslate"> | <div class="highlight-doscon notranslate"> | ||
第75行: | 第60行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="doscon">C:\Users\YourName> py</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 然后你应该看到类似的东西: | |
<div class="highlight-pycon notranslate"> | <div class="highlight-pycon notranslate"> | ||
第86行: | 第71行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="pycon">Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:04:45) [MSC v.1900 32 bit (Intel)] on win32 |
− | Type | + | Type "help", "copyright", "credits" or "license" for more information. |
− | + | >>></syntaxhighlight> | |
</div> | </div> | ||
</div> | </div> | ||
− | + | 您已经在“交互模式”下启动了解释器。 这意味着您可以交互式地输入 Python 语句或表达式,并在等待时执行或评估它们。 这是 Python 最强大的特性之一。 通过输入您选择的几个表达式并查看结果来检查它: | |
− | Python | ||
− | |||
− | |||
<div class="highlight-pycon notranslate"> | <div class="highlight-pycon notranslate"> | ||
第102行: | 第84行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="pycon">>>> print("Hello") |
Hello | Hello | ||
− | + | >>> "Hello" * 3 | |
− | 'HelloHelloHello'</ | + | 'HelloHelloHello'</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 许多人将交互模式用作方便但高度可编程的计算器。 当您想结束交互式 Python 会话时,请调用 [[../../library/constants#exit|exit()]] 函数或在输入 <span class="kbd kbd docutils literal notranslate">Z</span> 时按住 <span class="kbd kbd docutils literal notranslate">Ctrl</span> 键,然后点击“ <span class="kbd kbd docutils literal notranslate">回车</span>”键回到你的Windows命令提示符。 | |
− | |||
− | |||
− | |||
− | |||
− | + | 您可能还会发现您有一个开始菜单条目,例如 <span class="menuselection">Start ‣ Programs ‣ Python 3.x ‣ Python (command line)</span> 导致您在新的窗口中看到 <code>>>></code> 提示窗户。 如果是这样,调用[[../../library/constants#exit|exit()]]函数或输入<span class="kbd kbd compound docutils literal notranslate">Ctrl-Z</span>字符后,窗口就会消失; Windows 正在窗口中运行单个“python”命令,并在您终止解释器时关闭它。 | |
− | ‣ Programs ‣ Python 3.x ‣ Python (command line)</span> | ||
− | |||
− | |||
− | |||
− | |||
− | + | 现在我们知道 <code>py</code> 命令已被识别,您可以将 Python 脚本提供给它。 您必须提供 Python 脚本的绝对路径或相对路径。 假设您的 Python 脚本位于您的桌面并命名为 <code>hello.py</code>,并且您的命令提示符很好地在您的主目录中打开,因此您会看到类似以下内容: | |
− | Python | ||
− | |||
− | |||
− | |||
− | |||
<div class="highlight-none notranslate"> | <div class="highlight-none notranslate"> | ||
第134行: | 第102行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | <pre>C:\Users\YourName></pre> | + | <pre class="none">C:\Users\YourName></pre> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 因此,现在您将要求 <code>py</code> 命令通过键入 <code>py</code> 后跟您的脚本路径来将您的脚本提供给 Python: | |
− | |||
<div class="highlight-none notranslate"> | <div class="highlight-none notranslate"> | ||
第146行: | 第113行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | <pre>C:\Users\YourName> py Desktop\hello.py | + | <pre class="none">C:\Users\YourName> py Desktop\hello.py |
hello</pre> | hello</pre> | ||
第156行: | 第123行: | ||
<div id="how-do-i-make-python-scripts-executable" class="section"> | <div id="how-do-i-make-python-scripts-executable" class="section"> | ||
− | == | + | == 如何使 Python 脚本可执行? == |
− | + | 在 Windows 上,标准 Python 安装程序已经将 .py 扩展名与文件类型 (Python.File) 相关联,并为该文件类型提供了一个运行解释器 (<code>D:\Program Files\Python\python.exe "%1" %*</code>) 的打开命令。 这足以使脚本从命令提示符可执行为“foo.py”。 如果您希望能够通过简单地键入不带扩展名的“foo”来执行脚本,则需要将 .py 添加到 PATHEXT 环境变量中。 | |
− | |||
− | |||
− | |||
− | |||
第168行: | 第131行: | ||
<div id="why-does-python-sometimes-take-so-long-to-start" class="section"> | <div id="why-does-python-sometimes-take-so-long-to-start" class="section"> | ||
− | == | + | == 为什么 Python 有时需要很长时间才能启动? == |
− | + | 通常 Python 在 Windows 上启动非常快,但偶尔会有 bug 报告说 Python 突然开始需要很长时间才能启动。 这更令人费解,因为 Python 在其他配置相同的 Windows 系统上也能正常工作。 | |
− | |||
− | |||
− | |||
− | + | 该问题可能是由问题机器上的病毒检查软件配置错误引起的。 已知某些病毒扫描程序在将扫描程序配置为监视来自文件系统的所有读取时会引入两个数量级的启动开销。 尝试检查系统上病毒扫描软件的配置,以确保它们的配置确实相同。 当配置为扫描所有文件系统读取活动时,McAfee 是一个特殊的罪犯。 | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
第187行: | 第141行: | ||
<div id="how-do-i-make-an-executable-from-a-python-script" class="section"> | <div id="how-do-i-make-an-executable-from-a-python-script" class="section"> | ||
− | == | + | == 如何从 Python 脚本制作可执行文件? == |
− | + | 请参阅 [[../programming#faq-create-standalone-binary|如何从 Python 脚本创建独立的二进制文件?]] 以获取可用于制作可执行文件的工具列表。 | |
− | |||
− | |||
− | |||
− | |||
第199行: | 第149行: | ||
<div id="is-a-pyd-file-the-same-as-a-dll" class="section"> | <div id="is-a-pyd-file-the-same-as-a-dll" class="section"> | ||
− | == | + | == *.pyd 文件与 DLL 相同吗? == |
− | + | 是的,.pyd 文件是 dll,但有一些区别。 如果你有一个名为 <code>foo.pyd</code> 的 DLL,那么它必须有一个函数 <code>PyInit_foo()</code>。 然后,您可以编写 Python “import foo”,Python 将搜索 foo.pyd(以及 foo.py、foo.pyc),如果找到,将尝试调用 <code>PyInit_foo()</code> 对其进行初始化。 您不要将 .exe 与 foo.lib 链接,因为这会导致 Windows 要求存在 DLL。 | |
− | |||
− | |||
− | foo. | ||
− | |||
− | Windows | ||
− | + | 请注意,foo.pyd 的搜索路径是 PYTHONPATH,与 Windows 用于搜索 foo.dll 的路径不同。 此外,运行您的程序不需要 foo.pyd,而如果您将程序与 dll 链接,则需要 dll。 当然,如果要说<code>import foo</code>,则需要foo.pyd。 在 DLL 中,链接在源代码中用 <code>__declspec(dllexport)</code> 声明。 在 .pyd 中,链接在可用函数列表中定义。 | |
− | |||
− | |||
− | |||
− | |||
− | |||
第219行: | 第159行: | ||
<div id="how-can-i-embed-python-into-a-windows-application" class="section"> | <div id="how-can-i-embed-python-into-a-windows-application" class="section"> | ||
− | == | + | == 如何将 Python 嵌入到 Windows 应用程序中? == |
− | + | 在 Windows 应用程序中嵌入 Python 解释器可以总结如下: | |
<ol> | <ol> | ||
− | <li><p> | + | <li><p>不要_不要_直接将 Python 构建到您的 .exe 文件中。 在 Windows 上,Python 必须是一个 DLL 来处理导入模块本身就是 DLL 的。 (这是第一个未记录的关键事实。)相反,链接到 <code>pythonNN.dll</code>; 它通常安装在 <code>C:\Windows\System</code> 中。 ''NN'' 是 Python 版本,Python 3.3 中的数字如“33”。</p> |
− | + | <p>您可以通过两种不同的方式链接到 Python。 加载时链接意味着链接到 <code>pythonNN.lib</code>,而运行时链接意味着链接到 <code>pythonNN.dll</code>。 (一般注意:<code>pythonNN.lib</code>是所谓的“import lib”对应于<code>pythonNN.dll</code>。 它只是为链接器定义符号。)</p> | |
− | + | <p>运行时链接大大简化了链接选项; 一切都发生在运行时。 您的代码必须使用 Windows <code>LoadLibraryEx()</code> 例程加载 <code>pythonNN.dll</code>。 代码还必须使用通过 Windows <code>GetProcAddress()</code> 例程获得的指针,使用 <code>pythonNN.dll</code>(即 Python 的 C API)中的访问例程和数据。 宏可以使使用这些指针对调用 Python 的 C API 中的例程的任何 C 代码透明。</p> | |
− | + | <p>Borland 注意:首先使用 Coff2Omf.exe 将 <code>pythonNN.lib</code> 转换为 OMF 格式。</p></li> | |
− | + | <li><p>如果您使用 SWIG,很容易创建一个 Python“扩展模块”,使应用程序的数据和方法可用于 Python。 SWIG 将为您处理几乎所有脏乱的细节。 结果是您将 ''链接到'' .exe 文件的 C 代码(!)您_不必_创建一个 DLL 文件,这也简化了链接。</p></li> | |
− | <p> | + | <li><p>SWIG 将创建一个 init 函数(一个 C 函数),其名称取决于扩展模块的名称。 例如,如果模块的名称是 leo,则 init 函数将调用 initleo()。 如果您使用 SWIG 影子类,那么 init 函数将被称为 initleoc()。 这将初始化一个由 shadow 类使用的大部分隐藏的 helper 类。</p> |
− | + | <p>您可以将第 2 步中的 C 代码链接到您的 .exe 文件的原因是调用初始化函数相当于将模块导入 Python! (这是第二个未记录的关键事实。)</p></li> | |
− | + | <li><p>简而言之,您可以使用以下代码用您的扩展模块初始化 Python 解释器。</p> | |
− | |||
− | |||
− | <p> | ||
− | |||
− | <code>LoadLibraryEx()</code> | ||
− | |||
− | |||
− | |||
− | <p>Borland | ||
− | |||
− | <li><p> | ||
− | |||
− | |||
− | '' | ||
− | |||
− | <li><p>SWIG | ||
− | |||
− | |||
− | |||
− | |||
− | <p> | ||
− | |||
− | |||
− | <li><p> | ||
− | |||
<div class="highlight-c notranslate"> | <div class="highlight-c notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="c">#include "python.h" |
... | ... | ||
Py_Initialize(); // Initialize Python. | Py_Initialize(); // Initialize Python. | ||
initmyAppc(); // Initialize (import) the helper class. | initmyAppc(); // Initialize (import) the helper class. | ||
− | PyRun_SimpleString( | + | PyRun_SimpleString("import myApp"); // Import the shadow class.</syntaxhighlight> |
</div> | </div> | ||
</div></li> | </div></li> | ||
− | <li><p> | + | <li><p>Python 的 C API 有两个问题,如果您使用 MSVC 以外的编译器(用于构建 pythonNN.dll 的编译器),这两个问题就会变得很明显。</p> |
− | + | <p>问题 1:采用 FILE * 参数的所谓“非常高级”函数在多编译器环境中不起作用,因为每个编译器对 struct FILE 的概念是不同的。 从实现的角度来看,这些是非常低级的功能。</p> | |
− | <p> | + | <p>问题 2:SWIG 在为 void 函数生成包装器时生成以下代码:</p> |
− | |||
− | |||
− | |||
− | <p> | ||
− | |||
<div class="highlight-c notranslate"> | <div class="highlight-c notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="c">Py_INCREF(Py_None); |
_resultobj = Py_None; | _resultobj = Py_None; | ||
− | return _resultobj;</ | + | return _resultobj;</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>唉,Py_None 是一个宏,它扩展为对 pythonNN.dll 中名为 _Py_NoneStruct 的复杂数据结构的引用。 同样,此代码将在多编译器环境中失败。 将此类代码替换为:</p> |
− | |||
− | |||
<div class="highlight-c notranslate"> | <div class="highlight-c notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="c">return Py_BuildValue("");</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>可以使用 SWIG 的 <code>%typemap</code> 命令自动进行更改,但我无法使其正常工作(我是一个完整的 SWIG 新手)。</p></li> |
− | + | <li><p>使用 Python shell 脚本从 Windows 应用程序内部建立 Python 解释器窗口不是一个好主意; 生成的窗口将独立于您的应用程序的窗口系统。 相反,您(或 wxPythonWindow 类)应该创建一个“本机”解释器窗口。 将该窗口连接到 Python 解释器很容易。 您可以将 Python 的 i/o 重定向到支持读写的 _any_ 对象,因此您只需要一个包含 read() 和 write() 方法的 Python 对象(在您的扩展模块中定义)。</p></li></ol> | |
− | |||
− | <li><p> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
第316行: | 第216行: | ||
<div id="how-do-i-keep-editors-from-inserting-tabs-into-my-python-source" class="section"> | <div id="how-do-i-keep-editors-from-inserting-tabs-into-my-python-source" class="section"> | ||
− | == | + | == 如何防止编辑器将选项卡插入到我的 Python 源代码中? == |
− | + | FAQ不推荐使用tabs,Python风格指南<span id="index-0" class="target"></span>[https://www.python.org/dev/peps/pep-0008 PEP 8]推荐4个空格用于分布式Python代码; 这也是 Emacs python 模式的默认值。 | |
− | |||
− | python | ||
− | + | 在任何编辑器下,混合制表符和空格都是一个坏主意。 MSVC 在这方面没有什么不同,并且很容易配置为使用空格:取 <span class="menuselection">Tools ‣ Options ‣ Tabs</span>,并将文件类型“默认”设置“制表符大小”和“缩进大小”为 4,然后选择“插入空格”单选按钮。 | |
− | |||
− | ‣ Options ‣ Tabs</span> | ||
− | |||
− | + | 如果混合制表符和空格导致前导空格出现问题,Python 会引发 [[../../library/exceptions#IndentationError|IndentationError]] 或 [[../../library/exceptions#TabError|TabError]]。 您还可以运行 [[../../library/tabnanny#module-tabnanny|tabnanny]] 模块以批处理模式检查目录树。 | |
− | |||
− | |||
− | |||
第336行: | 第228行: | ||
<div id="how-do-i-check-for-a-keypress-without-blocking" class="section"> | <div id="how-do-i-check-for-a-keypress-without-blocking" class="section"> | ||
− | == | + | == 如何在不阻塞的情况下检查按键? == |
− | + | 使用 [[../../library/msvcrt#module-msvcrt|msvcrt]] 模块。 这是一个标准的 Windows 特定的扩展模块。 它定义了一个函数 <code>kbhit()</code> 来检查是否存在键盘敲击,以及 <code>getch()</code> 获取一个字符而不回显它。 | |
− | |||
− | |||
第346行: | 第236行: | ||
</div> | </div> | ||
+ | <div class="clearer"> | ||
− | [[Category:Python 3.9 | + | |
+ | |||
+ | </div> | ||
+ | |||
+ | [[Category:Python 3.9 文档]] |
2021年10月31日 (日) 04:50的最新版本
Windows 上的 Python 常见问题解答
如何在 Windows 下运行 Python 程序?
这不一定是一个直截了当的问题。 如果您已经熟悉从 Windows 命令行运行程序,那么一切都将显而易见; 否则,您可能需要更多指导。
除非您使用某种集成开发环境,否则您最终将 将 Windows 命令输入到各种称为“DOS 窗口”或“命令提示符窗口”的地方。 通常,您可以通过搜索 cmd
从搜索栏中创建这样的窗口。 您应该能够识别何时启动了这样的窗口,因为您会看到一个 Windows“命令提示符”,通常如下所示:
这封信可能不同,后面可能还有其他内容,因此您可能很容易看到以下内容:
取决于您的计算机是如何设置的以及您最近对它做了什么。 一旦您启动了这样一个窗口,您就可以很好地运行 Python 程序了。
您需要意识到您的 Python 脚本必须由另一个名为 Python 解释器 的程序处理。 解释器读取您的脚本,将其编译为字节码,然后执行字节码以运行您的程序。 那么,你如何安排解释器来处理你的 Python?
首先,您需要确保您的命令窗口将单词“py”识别为启动解释器的指令。 如果您打开了命令窗口,您应该尝试输入命令 py
并按回车键:
然后你应该看到类似的东西:
您已经在“交互模式”下启动了解释器。 这意味着您可以交互式地输入 Python 语句或表达式,并在等待时执行或评估它们。 这是 Python 最强大的特性之一。 通过输入您选择的几个表达式并查看结果来检查它:
许多人将交互模式用作方便但高度可编程的计算器。 当您想结束交互式 Python 会话时,请调用 exit() 函数或在输入 Z 时按住 Ctrl 键,然后点击“ 回车”键回到你的Windows命令提示符。
您可能还会发现您有一个开始菜单条目,例如 >>>
提示窗户。 如果是这样,调用exit()函数或输入Ctrl-Z字符后,窗口就会消失; Windows 正在窗口中运行单个“python”命令,并在您终止解释器时关闭它。
现在我们知道 py
命令已被识别,您可以将 Python 脚本提供给它。 您必须提供 Python 脚本的绝对路径或相对路径。 假设您的 Python 脚本位于您的桌面并命名为 hello.py
,并且您的命令提示符很好地在您的主目录中打开,因此您会看到类似以下内容:
C:\Users\YourName>
因此,现在您将要求 py
命令通过键入 py
后跟您的脚本路径来将您的脚本提供给 Python:
C:\Users\YourName> py Desktop\hello.py
hello
如何使 Python 脚本可执行?
在 Windows 上,标准 Python 安装程序已经将 .py 扩展名与文件类型 (Python.File) 相关联,并为该文件类型提供了一个运行解释器 (D:\Program Files\Python\python.exe "%1" %*
) 的打开命令。 这足以使脚本从命令提示符可执行为“foo.py”。 如果您希望能够通过简单地键入不带扩展名的“foo”来执行脚本,则需要将 .py 添加到 PATHEXT 环境变量中。
为什么 Python 有时需要很长时间才能启动?
通常 Python 在 Windows 上启动非常快,但偶尔会有 bug 报告说 Python 突然开始需要很长时间才能启动。 这更令人费解,因为 Python 在其他配置相同的 Windows 系统上也能正常工作。
该问题可能是由问题机器上的病毒检查软件配置错误引起的。 已知某些病毒扫描程序在将扫描程序配置为监视来自文件系统的所有读取时会引入两个数量级的启动开销。 尝试检查系统上病毒扫描软件的配置,以确保它们的配置确实相同。 当配置为扫描所有文件系统读取活动时,McAfee 是一个特殊的罪犯。
*.pyd 文件与 DLL 相同吗?
是的,.pyd 文件是 dll,但有一些区别。 如果你有一个名为 foo.pyd
的 DLL,那么它必须有一个函数 PyInit_foo()
。 然后,您可以编写 Python “import foo”,Python 将搜索 foo.pyd(以及 foo.py、foo.pyc),如果找到,将尝试调用 PyInit_foo()
对其进行初始化。 您不要将 .exe 与 foo.lib 链接,因为这会导致 Windows 要求存在 DLL。
请注意,foo.pyd 的搜索路径是 PYTHONPATH,与 Windows 用于搜索 foo.dll 的路径不同。 此外,运行您的程序不需要 foo.pyd,而如果您将程序与 dll 链接,则需要 dll。 当然,如果要说import foo
,则需要foo.pyd。 在 DLL 中,链接在源代码中用 __declspec(dllexport)
声明。 在 .pyd 中,链接在可用函数列表中定义。
如何将 Python 嵌入到 Windows 应用程序中?
在 Windows 应用程序中嵌入 Python 解释器可以总结如下:
不要_不要_直接将 Python 构建到您的 .exe 文件中。 在 Windows 上,Python 必须是一个 DLL 来处理导入模块本身就是 DLL 的。 (这是第一个未记录的关键事实。)相反,链接到
pythonNN.dll
; 它通常安装在C:\Windows\System
中。 NN 是 Python 版本,Python 3.3 中的数字如“33”。您可以通过两种不同的方式链接到 Python。 加载时链接意味着链接到
pythonNN.lib
,而运行时链接意味着链接到pythonNN.dll
。 (一般注意:pythonNN.lib
是所谓的“import lib”对应于pythonNN.dll
。 它只是为链接器定义符号。)运行时链接大大简化了链接选项; 一切都发生在运行时。 您的代码必须使用 Windows
LoadLibraryEx()
例程加载pythonNN.dll
。 代码还必须使用通过 WindowsGetProcAddress()
例程获得的指针,使用pythonNN.dll
(即 Python 的 C API)中的访问例程和数据。 宏可以使使用这些指针对调用 Python 的 C API 中的例程的任何 C 代码透明。Borland 注意:首先使用 Coff2Omf.exe 将
pythonNN.lib
转换为 OMF 格式。如果您使用 SWIG,很容易创建一个 Python“扩展模块”,使应用程序的数据和方法可用于 Python。 SWIG 将为您处理几乎所有脏乱的细节。 结果是您将 链接到 .exe 文件的 C 代码(!)您_不必_创建一个 DLL 文件,这也简化了链接。
SWIG 将创建一个 init 函数(一个 C 函数),其名称取决于扩展模块的名称。 例如,如果模块的名称是 leo,则 init 函数将调用 initleo()。 如果您使用 SWIG 影子类,那么 init 函数将被称为 initleoc()。 这将初始化一个由 shadow 类使用的大部分隐藏的 helper 类。
您可以将第 2 步中的 C 代码链接到您的 .exe 文件的原因是调用初始化函数相当于将模块导入 Python! (这是第二个未记录的关键事实。)
简而言之,您可以使用以下代码用您的扩展模块初始化 Python 解释器。
Python 的 C API 有两个问题,如果您使用 MSVC 以外的编译器(用于构建 pythonNN.dll 的编译器),这两个问题就会变得很明显。
问题 1:采用 FILE * 参数的所谓“非常高级”函数在多编译器环境中不起作用,因为每个编译器对 struct FILE 的概念是不同的。 从实现的角度来看,这些是非常低级的功能。
问题 2:SWIG 在为 void 函数生成包装器时生成以下代码:
唉,Py_None 是一个宏,它扩展为对 pythonNN.dll 中名为 _Py_NoneStruct 的复杂数据结构的引用。 同样,此代码将在多编译器环境中失败。 将此类代码替换为:
可以使用 SWIG 的
%typemap
命令自动进行更改,但我无法使其正常工作(我是一个完整的 SWIG 新手)。使用 Python shell 脚本从 Windows 应用程序内部建立 Python 解释器窗口不是一个好主意; 生成的窗口将独立于您的应用程序的窗口系统。 相反,您(或 wxPythonWindow 类)应该创建一个“本机”解释器窗口。 将该窗口连接到 Python 解释器很容易。 您可以将 Python 的 i/o 重定向到支持读写的 _any_ 对象,因此您只需要一个包含 read() 和 write() 方法的 Python 对象(在您的扩展模块中定义)。
如何防止编辑器将选项卡插入到我的 Python 源代码中?
FAQ不推荐使用tabs,Python风格指南PEP 8推荐4个空格用于分布式Python代码; 这也是 Emacs python 模式的默认值。
在任何编辑器下,混合制表符和空格都是一个坏主意。 MSVC 在这方面没有什么不同,并且很容易配置为使用空格:取
,并将文件类型“默认”设置“制表符大小”和“缩进大小”为 4,然后选择“插入空格”单选按钮。如果混合制表符和空格导致前导空格出现问题,Python 会引发 IndentationError 或 TabError。 您还可以运行 tabnanny 模块以批处理模式检查目录树。
如何在不阻塞的情况下检查按键?
使用 msvcrt 模块。 这是一个标准的 Windows 特定的扩展模块。 它定义了一个函数 kbhit()
来检查是否存在键盘敲击,以及 getch()
获取一个字符而不回显它。