561 lines
55 KiB
HTML
561 lines
55 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
|
||
<head>
|
||
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||
|
||
<title>cgi --- 通用网关接口支持 — Python 3.8.20 文档</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
||
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
|
||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||
<script src="../_static/jquery.js"></script>
|
||
<script src="../_static/underscore.js"></script>
|
||
<script src="../_static/doctools.js"></script>
|
||
<script src="../_static/language_data.js"></script>
|
||
<script src="../_static/translations.js"></script>
|
||
|
||
<script src="../_static/sidebar.js"></script>
|
||
|
||
<link rel="search" type="application/opensearchdescription+xml"
|
||
title="在 Python 3.8.20 文档 中搜索"
|
||
href="../_static/opensearch.xml"/>
|
||
<link rel="author" title="关于这些文档" href="../about.html" />
|
||
<link rel="index" title="索引" href="../genindex.html" />
|
||
<link rel="search" title="搜索" href="../search.html" />
|
||
<link rel="copyright" title="版权所有" href="../copyright.html" />
|
||
<link rel="next" title="cgitb --- 用于 CGI 脚本的回溯管理器" href="cgitb.html" />
|
||
<link rel="prev" title="webbrowser --- 方便的Web浏览器控制器" href="webbrowser.html" />
|
||
<link rel="canonical" href="https://docs.python.org/3/library/cgi.html" />
|
||
|
||
|
||
|
||
|
||
|
||
<style>
|
||
@media only screen {
|
||
table.full-width-table {
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style>
|
||
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
|
||
<script type="text/javascript" src="../_static/copybutton.js"></script>
|
||
<script type="text/javascript" src="../_static/menu.js"></script>
|
||
|
||
</head>
|
||
<body>
|
||
<div class="mobile-nav">
|
||
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
|
||
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
|
||
<label for="menuToggler" class="toggler__label">
|
||
<span></span>
|
||
</label>
|
||
<nav class="nav-content" role="navigation">
|
||
<a href="https://www.python.org/" class="nav-logo">
|
||
<img src="../_static/py.svg" alt="Logo"/>
|
||
</a>
|
||
<div class="version_switcher_placeholder"></div>
|
||
<form role="search" class="search" action="../search.html" method="get">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
|
||
<path fill-rule="nonzero"
|
||
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
|
||
</svg>
|
||
<input type="text" name="q" aria-label="快速搜索"/>
|
||
<input type="submit" value="转向"/>
|
||
</form>
|
||
</nav>
|
||
<div class="menu-wrapper">
|
||
<nav class="menu" role="navigation" aria-label="main navigation">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<h3><a href="../contents.html">目录</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">cgi</span></code> --- 通用网关接口支持</a><ul>
|
||
<li><a class="reference internal" href="#introduction">概述</a></li>
|
||
<li><a class="reference internal" href="#using-the-cgi-module">使用 cgi 模块</a></li>
|
||
<li><a class="reference internal" href="#higher-level-interface">更高层级的接口</a></li>
|
||
<li><a class="reference internal" href="#functions">函数</a></li>
|
||
<li><a class="reference internal" href="#caring-about-security">对于安全性的关注</a></li>
|
||
<li><a class="reference internal" href="#installing-your-cgi-script-on-a-unix-system">在 Unix 系统上安装你的 CGI 脚本</a></li>
|
||
<li><a class="reference internal" href="#testing-your-cgi-script">测试你的 CGI 脚本</a></li>
|
||
<li><a class="reference internal" href="#debugging-cgi-scripts">调试 CGI 脚本</a></li>
|
||
<li><a class="reference internal" href="#common-problems-and-solutions">常见问题和解决方案</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="webbrowser.html"
|
||
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">webbrowser</span></code> --- 方便的Web浏览器控制器</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="cgitb.html"
|
||
title="下一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">cgitb</span></code> --- 用于 CGI 脚本的回溯管理器</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<h3>本页</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">报告 Bug</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.8/Doc/library/cgi.rst"
|
||
rel="nofollow">显示源代码
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="outdated-warning" style="padding: .5em; text-align: center; background-color: #FFBABA; color: #6A0E0E;">
|
||
这个文档所针对的是一个已不再受支持的 Python 旧版本。
|
||
你应当升级版本,并阅读
|
||
<a href="/3/library/cgi.html"> Python 当前稳定版本的文档</a>.
|
||
</div>
|
||
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>导航</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="总目录"
|
||
accesskey="I">索引</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python 模块索引"
|
||
>模块</a> |</li>
|
||
<li class="right" >
|
||
<a href="cgitb.html" title="cgitb --- 用于 CGI 脚本的回溯管理器"
|
||
accesskey="N">下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="webbrowser.html" title="webbrowser --- 方便的Web浏览器控制器"
|
||
accesskey="P">上一页</a> |</li>
|
||
|
||
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.8.20 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="internet.html" accesskey="U">互联网协议和支持</a> »</li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
|
||
<input type="submit" value="转向" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section id="module-cgi">
|
||
<span id="cgi-common-gateway-interface-support"></span><h1><a class="reference internal" href="#module-cgi" title="cgi: Helpers for running Python scripts via the Common Gateway Interface."><code class="xref py py-mod docutils literal notranslate"><span class="pre">cgi</span></code></a> --- 通用网关接口支持<a class="headerlink" href="#module-cgi" title="永久链接至标题">¶</a></h1>
|
||
<p><strong>源代码:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/3.8/Lib/cgi.py">Lib/cgi.py</a></p>
|
||
<hr class="docutils" id="index-0" />
|
||
<p>通用网关接口 (CGI) 脚本的支持模块</p>
|
||
<p>本模块定义了一些工具供以 Python 编写的 CGI 脚本使用。</p>
|
||
<section id="introduction">
|
||
<h2>概述<a class="headerlink" href="#introduction" title="永久链接至标题">¶</a></h2>
|
||
<p id="cgi-intro">CGI 脚本是由 HTTP 服务器发起调用,通常用来处理通过 HTML <code class="docutils literal notranslate"><span class="pre"><FORM></span></code> 或 <code class="docutils literal notranslate"><span class="pre"><ISINDEX></span></code> 元素提交的用户输入。</p>
|
||
<p>在大多数情况下,CGI 脚本存放在服务器的 <code class="file docutils literal notranslate"><span class="pre">cgi-bin</span></code> 特殊目录下。 HTTP 服务器将有关请求的各种信息(例如客户端的主机名、所请求的 URL、查询字符串以及许多其他内容)放在脚本的 shell 环境中,然后执行脚本,并将脚本的输出发回到客户端。</p>
|
||
<p>脚本的输入也会被连接到客户端,并且有时表单数据也会以此方式来读取;在其他时候表单数据会通过 URL 的“查询字符串”部分来传递。 本模块的目标是处理不同的应用场景并向 Python 脚本提供一个更为简单的接口。 它还提供了一些工具为脚本调试提供帮助,而最近增加的还有对通过表单上传文件的支持(如果你的浏览器支持该功能的话)。</p>
|
||
<p>CGI 脚本的输出应当由两部分组成,并由一个空行分隔。 前一部分包含一些标头,它们告诉客户端后面会提供何种数据。 生成一个最小化标头部分的 Python 代码如下所示:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="s2">"Content-Type: text/html"</span><span class="p">)</span> <span class="c1"># HTML is following</span>
|
||
<span class="nb">print</span><span class="p">()</span> <span class="c1"># blank line, end of headers</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>后一部分通常为 HTML,提供给客户端软件来显示格式良好包含标题的文本、内联图片等内容。 下面是打印一段简单 HTML 的 Python 代码:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="s2">"<TITLE>CGI script output</TITLE>"</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"<H1>This is my first CGI script</H1>"</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Hello, world!"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="using-the-cgi-module">
|
||
<span id="id1"></span><h2>使用 cgi 模块<a class="headerlink" href="#using-the-cgi-module" title="永久链接至标题">¶</a></h2>
|
||
<p>先在开头添加 <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">cgi</span></code>。</p>
|
||
<p>当你在编写一个新脚本时,请考虑加上这些语句:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">cgitb</span>
|
||
<span class="n">cgitb</span><span class="o">.</span><span class="n">enable</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这会激活一个特殊的异常处理器,它将在发生任何错误时将详细错误报告显示到 Web 浏览器中。 如果你不希望向你的脚本 的用户显示你的程序的内部细节,你可以改为将报告保存到文件中,使用这样的代码即可:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">cgitb</span>
|
||
<span class="n">cgitb</span><span class="o">.</span><span class="n">enable</span><span class="p">(</span><span class="n">display</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">logdir</span><span class="o">=</span><span class="s2">"/path/to/logdir"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在脚本开发期间使用此特性会很有帮助。 <a class="reference internal" href="cgitb.html#module-cgitb" title="cgitb: Configurable traceback handler for CGI scripts."><code class="xref py py-mod docutils literal notranslate"><span class="pre">cgitb</span></code></a> 所产生的报告提供了在追踪程序问题时能为你节省大量时间的信息。 你可以在完成测试你的脚本并确信它能正确工作之后再移除 <code class="docutils literal notranslate"><span class="pre">cgitb</span></code> 行。</p>
|
||
<p>要获取提交的表单数据,请使用 <code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 类。 如果表单包含非 ASCII 字符,请使用 <em>encoding</em> 关键字参数并设置为文档所定义的编码格式值。 它通常包含在 HTML 文档的 HEAD 部分的 META 标签中或者由 <em class="mailheader">Content-Type</em> 标头所指明。 这会从标准输入或环境读取表单内容(取决于根据 CGI 标准设置的多个环境变量的值)。 由于它可能会消耗标准输入,它应当只被实例化一次。</p>
|
||
<p><code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 实例可以像 Python 字典一样来检索。 它允许通过 <a class="reference internal" href="../reference/expressions.html#in"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">in</span></code></a> 运算符进行成员检测,也支持标准字典方法 <a class="reference internal" href="stdtypes.html#dict.keys" title="dict.keys"><code class="xref py py-meth docutils literal notranslate"><span class="pre">keys()</span></code></a> 和内置函数 <a class="reference internal" href="functions.html#len" title="len"><code class="xref py py-func docutils literal notranslate"><span class="pre">len()</span></code></a>。 包含空字符串的表单字段会被忽略而不会出现在字典中;要保留这样的值,请在创建 <code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 实例时为可选的 <em>keep_blank_values</em> 关键字形参提供一个真值。</p>
|
||
<p>举例来说,下面的代码(假定 <em class="mailheader">Content-Type</em> 标头和空行已经被打印)会检查字段 <code class="docutils literal notranslate"><span class="pre">name</span></code> 和 <code class="docutils literal notranslate"><span class="pre">addr</span></code> 是否均被设为非空字符串:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">form</span> <span class="o">=</span> <span class="n">cgi</span><span class="o">.</span><span class="n">FieldStorage</span><span class="p">()</span>
|
||
<span class="k">if</span> <span class="s2">"name"</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">form</span> <span class="ow">or</span> <span class="s2">"addr"</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">form</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"<H1>Error</H1>"</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Please fill in the name and addr fields."</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"<p>name:"</span><span class="p">,</span> <span class="n">form</span><span class="p">[</span><span class="s2">"name"</span><span class="p">]</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"<p>addr:"</span><span class="p">,</span> <span class="n">form</span><span class="p">[</span><span class="s2">"addr"</span><span class="p">]</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
||
<span class="o">...</span><span class="n">further</span> <span class="n">form</span> <span class="n">processing</span> <span class="n">here</span><span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在这里的字段通过 <code class="docutils literal notranslate"><span class="pre">form[key]</span></code> 来访问,它们本身就是 <code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> (或 <code class="xref py py-class docutils literal notranslate"><span class="pre">MiniFieldStorage</span></code>,取决于表单的编码格式) 的实例。 实例的 <code class="xref py py-attr docutils literal notranslate"><span class="pre">value</span></code> 属性会产生字段的字符串值。 <code class="xref py py-meth docutils literal notranslate"><span class="pre">getvalue()</span></code> 方法直接返回这个字符串;它还接受可选的第二个参数作为当请求的键不存在时要返回的默认值。</p>
|
||
<p>如果提交的表单数据包含一个以上的同名字段,由 <code class="docutils literal notranslate"><span class="pre">form[key]</span></code> 所提取的对象将不是一个 <code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 或 <code class="xref py py-class docutils literal notranslate"><span class="pre">MiniFieldStorage</span></code> 实例而是由这种实例组成的列表。 类似地,在这种情况下,<code class="docutils literal notranslate"><span class="pre">form.getvalue(key)</span></code> 将会返回一个字符串列表。 如果你预计到这种可能性(当你的 HTML 表单包含多个同名字段时),请使用 <a class="reference internal" href="#cgi.FieldStorage.getlist" title="cgi.FieldStorage.getlist"><code class="xref py py-meth docutils literal notranslate"><span class="pre">getlist()</span></code></a> 方法,它总是返回一个值的列表(这样你就不需要对只有单个项的情况进行特别处理)。 例如,这段代码拼接了任意数量的 username 字段,以逗号进行分隔:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">value</span> <span class="o">=</span> <span class="n">form</span><span class="o">.</span><span class="n">getlist</span><span class="p">(</span><span class="s2">"username"</span><span class="p">)</span>
|
||
<span class="n">usernames</span> <span class="o">=</span> <span class="s2">","</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>如果一个字段是代表上传的文件,请通过 <code class="xref py py-attr docutils literal notranslate"><span class="pre">value</span></code> 属性访问该值或是通过 <code class="xref py py-meth docutils literal notranslate"><span class="pre">getvalue()</span></code> 方法以字节形式将整个文件读入内存。 这可能不是你想要的结果。 你可以通过测试 <code class="xref py py-attr docutils literal notranslate"><span class="pre">filename</span></code> 属性或 <code class="xref py py-attr docutils literal notranslate"><span class="pre">file</span></code> 属性来检测上传的文件。 然后你可以从 <code class="xref py py-attr docutils literal notranslate"><span class="pre">file</span></code> 属性读取数据,直到它作为 <code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 实例的垃圾回收的一部分被自动关闭 (<a class="reference internal" href="io.html#io.RawIOBase.read" title="io.RawIOBase.read"><code class="xref py py-func docutils literal notranslate"><span class="pre">read()</span></code></a> 和 <a class="reference internal" href="io.html#io.IOBase.readline" title="io.IOBase.readline"><code class="xref py py-func docutils literal notranslate"><span class="pre">readline()</span></code></a> 方法将返回字节数据):</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">fileitem</span> <span class="o">=</span> <span class="n">form</span><span class="p">[</span><span class="s2">"userfile"</span><span class="p">]</span>
|
||
<span class="k">if</span> <span class="n">fileitem</span><span class="o">.</span><span class="n">file</span><span class="p">:</span>
|
||
<span class="c1"># It's an uploaded file; count lines</span>
|
||
<span class="n">linecount</span> <span class="o">=</span> <span class="mi">0</span>
|
||
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
||
<span class="n">line</span> <span class="o">=</span> <span class="n">fileitem</span><span class="o">.</span><span class="n">file</span><span class="o">.</span><span class="n">readline</span><span class="p">()</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">line</span><span class="p">:</span> <span class="k">break</span>
|
||
<span class="n">linecount</span> <span class="o">=</span> <span class="n">linecount</span> <span class="o">+</span> <span class="mi">1</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 对象还支持在 <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> 语句中使用,该语句结束时将自动关闭它们。</p>
|
||
<p>如果在获取上传文件的内容时遇到错误(例如,当用户点击回退或取消按钮中断表单提交时)该字段中对象的 <code class="xref py py-attr docutils literal notranslate"><span class="pre">done</span></code> 属性值将被设为 -1。</p>
|
||
<p>文件上传标准草案考虑到了从一个字段上传多个文件的可能性(使用递归的 <em class="mimetype">multipart/*</em> 编码格式)。 当这种情况发生时,该条目将是一个类似字典的 <code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 条目。 这可以通过检测它的 <code class="xref py py-attr docutils literal notranslate"><span class="pre">type</span></code> 属性来确定,该属性应当是 <em class="mimetype">multipart/form-data</em> (或者可能是匹配 <em class="mimetype">multipart/*</em> 的其他 MIME 类型)。 在这种情况下,它可以像最高层级的表单对象一样被递归地迭代处理。</p>
|
||
<p>当一个表单按“旧”格式提交时(即以查询字符串或是单个 <em class="mimetype">application/x-www-form-urlencoded</em> 类型的数据部分的形式),这些条目实际上将是 <code class="xref py py-class docutils literal notranslate"><span class="pre">MiniFieldStorage</span></code> 类的实例。 在这种情况下,<code class="xref py py-attr docutils literal notranslate"><span class="pre">list</span></code>, <code class="xref py py-attr docutils literal notranslate"><span class="pre">file</span></code> 和 <code class="xref py py-attr docutils literal notranslate"><span class="pre">filename</span></code> 属性将总是为 <code class="docutils literal notranslate"><span class="pre">None</span></code>。</p>
|
||
<p>通过 POST 方式提交并且也带有查询字符串的表单将同时包含 <code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 和 <code class="xref py py-class docutils literal notranslate"><span class="pre">MiniFieldStorage</span></code> 条目。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.4 版更改: </span><code class="xref py py-attr docutils literal notranslate"><span class="pre">file</span></code> 属性会在创建 <code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 实例的垃圾回收操作中被自动关闭。</p>
|
||
</div>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.5 版更改: </span>为 <code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 类增加了上下文管理协议支持。</p>
|
||
</div>
|
||
</section>
|
||
<section id="higher-level-interface">
|
||
<h2>更高层级的接口<a class="headerlink" href="#higher-level-interface" title="永久链接至标题">¶</a></h2>
|
||
<p>前面的部分解释了如何使用 <code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 类来读取 CGI 表单数据。 本部分则会描述一个更高层级的接口,它被添加到此类中以允许人们以更为可读和自然的方式行事。 这个接口并不会完全取代前面的部分所描述的技巧 --- 例如它们在高效处理文件上传时仍然很有用处。</p>
|
||
<p>此接口由两个简单的方法组成。 你可以使用这两个方法以通用的方式处理表单数据,而无需担心在一个名称下提交的值是只有一个还是有多个。</p>
|
||
<p>在前面的部分中,你已学会当你预期用户在一个名称下提交超过一个值的时候编写以下代码:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">item</span> <span class="o">=</span> <span class="n">form</span><span class="o">.</span><span class="n">getvalue</span><span class="p">(</span><span class="s2">"item"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="nb">list</span><span class="p">):</span>
|
||
<span class="c1"># The user is requesting more than one item.</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># The user is requesting only one item.</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这种情况很常见,例如当一个表单包含具有相同名称的一组复选框的时候:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="o"><</span><span class="nb">input</span> <span class="nb">type</span><span class="o">=</span><span class="s2">"checkbox"</span> <span class="n">name</span><span class="o">=</span><span class="s2">"item"</span> <span class="n">value</span><span class="o">=</span><span class="s2">"1"</span> <span class="o">/></span>
|
||
<span class="o"><</span><span class="nb">input</span> <span class="nb">type</span><span class="o">=</span><span class="s2">"checkbox"</span> <span class="n">name</span><span class="o">=</span><span class="s2">"item"</span> <span class="n">value</span><span class="o">=</span><span class="s2">"2"</span> <span class="o">/></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>但是在多数情况下,一个表单中的一个特定名称只对应一个表单控件。 因此你可能会编写包含以下代码的脚本:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">user</span> <span class="o">=</span> <span class="n">form</span><span class="o">.</span><span class="n">getvalue</span><span class="p">(</span><span class="s2">"user"</span><span class="p">)</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这段代码的问题在于你绝不能预期客户端会向你的脚本提供合法的输入。 举例来说,如果一个好奇的用户向查询字符串添加了另一个 <code class="docutils literal notranslate"><span class="pre">user=foo</span></code> 对,则该脚本将会崩溃,因为在这种情况下 <code class="docutils literal notranslate"><span class="pre">getvalue("user")</span></code> 方法调用将返回一个列表而不是字符串。 在一个列表上调用 <a class="reference internal" href="stdtypes.html#str.upper" title="str.upper"><code class="xref py py-meth docutils literal notranslate"><span class="pre">upper()</span></code></a> 方法是不合法的(因为列表并没有这个方法)因而会引发 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a> 异常。</p>
|
||
<p>因此,读取表单数据值的正确方式应当总是使用检查所获取的值是单一值还是值列表的代码。 这很麻烦并且会使脚本缺乏可读性。</p>
|
||
<p>一种更便捷的方式是使用这个更高层级接口所提供的 <a class="reference internal" href="#cgi.FieldStorage.getfirst" title="cgi.FieldStorage.getfirst"><code class="xref py py-meth docutils literal notranslate"><span class="pre">getfirst()</span></code></a> 和 <a class="reference internal" href="#cgi.FieldStorage.getlist" title="cgi.FieldStorage.getlist"><code class="xref py py-meth docutils literal notranslate"><span class="pre">getlist()</span></code></a> 方法。</p>
|
||
<dl class="method">
|
||
<dt id="cgi.FieldStorage.getfirst">
|
||
<code class="sig-prename descclassname">FieldStorage.</code><code class="sig-name descname">getfirst</code><span class="sig-paren">(</span><em class="sig-param">name</em>, <em class="sig-param">default=None</em><span class="sig-paren">)</span><a class="headerlink" href="#cgi.FieldStorage.getfirst" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>此方法总是只返回与表单字段 <em>name</em> 相关联的单一值。 此方法在同一名称下提交了多个值的情况下将仅返回第一个值。 请注意所接收的值顺序在不同浏览器上可能发生变化因而是不确定的。 <a class="footnote-reference brackets" href="#id3" id="id2">1</a> 如果指定的表单字段或值不存在则此方法将返回可选形参 <em>default</em> 所指定的值。 如果未指定此形参则默认值为 <code class="docutils literal notranslate"><span class="pre">None</span></code>。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="cgi.FieldStorage.getlist">
|
||
<code class="sig-prename descclassname">FieldStorage.</code><code class="sig-name descname">getlist</code><span class="sig-paren">(</span><em class="sig-param">name</em><span class="sig-paren">)</span><a class="headerlink" href="#cgi.FieldStorage.getlist" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>此方法总是返回与表单字段 <em>name</em> 相关联的值列表。 如果 <em>name</em> 指定的表单字段或值不存在则此方法将返回一个空列表。 如果指定的表单字段只包含一个值则它将返回只有一项的列表。</p>
|
||
</dd></dl>
|
||
|
||
<p>使用这两个方法你将能写出优雅简洁的代码:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">cgi</span>
|
||
<span class="n">form</span> <span class="o">=</span> <span class="n">cgi</span><span class="o">.</span><span class="n">FieldStorage</span><span class="p">()</span>
|
||
<span class="n">user</span> <span class="o">=</span> <span class="n">form</span><span class="o">.</span><span class="n">getfirst</span><span class="p">(</span><span class="s2">"user"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span> <span class="c1"># This way it's safe.</span>
|
||
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">form</span><span class="o">.</span><span class="n">getlist</span><span class="p">(</span><span class="s2">"item"</span><span class="p">):</span>
|
||
<span class="n">do_something</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="functions">
|
||
<span id="functions-in-cgi-module"></span><h2>函数<a class="headerlink" href="#functions" title="永久链接至标题">¶</a></h2>
|
||
<p>这些函数在你想要更多控制,或者如果你想要应用一些此模块中在其他场景下实现的算法时很有用处。</p>
|
||
<dl class="function">
|
||
<dt id="cgi.parse">
|
||
<code class="sig-prename descclassname">cgi.</code><code class="sig-name descname">parse</code><span class="sig-paren">(</span><em class="sig-param">fp=None</em>, <em class="sig-param">environ=os.environ</em>, <em class="sig-param">keep_blank_values=False</em>, <em class="sig-param">strict_parsing=False</em>, <em class="sig-param">separator="&"</em><span class="sig-paren">)</span><a class="headerlink" href="#cgi.parse" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>在环境中或从某个文件中解析一个查询 (文件默认为 <code class="docutils literal notranslate"><span class="pre">sys.stdin</span></code>)。 <em>keep_blank_values</em>, <em>strict_parsing</em> 和 <em>separator</em> 形参会被原样传给 <a class="reference internal" href="urllib.parse.html#urllib.parse.parse_qs" title="urllib.parse.parse_qs"><code class="xref py py-func docutils literal notranslate"><span class="pre">urllib.parse.parse_qs()</span></code></a>。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8.8 版更改: </span>增加了 <em>separator</em> 形参。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="cgi.parse_multipart">
|
||
<code class="sig-prename descclassname">cgi.</code><code class="sig-name descname">parse_multipart</code><span class="sig-paren">(</span><em class="sig-param">fp</em>, <em class="sig-param">pdict</em>, <em class="sig-param">encoding="utf-8"</em>, <em class="sig-param">errors="replace"</em>, <em class="sig-param">separator="&"</em><span class="sig-paren">)</span><a class="headerlink" href="#cgi.parse_multipart" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>解析 <em class="mimetype">multipart/form-data</em> 类型(用于文件上传)的输入。 参数中 <em>fp</em> 为输入文件,<em>pdict</em> 为包含 <em class="mailheader">Content-Type</em> 标头中的其他形参的字典,<em>encoding</em> 为请求的编码格式。</p>
|
||
<p>像 <a class="reference internal" href="urllib.parse.html#urllib.parse.parse_qs" title="urllib.parse.parse_qs"><code class="xref py py-func docutils literal notranslate"><span class="pre">urllib.parse.parse_qs()</span></code></a> 那样返回一个字典:其中的键为字段名称,值为对应字段的值列表。 对于非文件字段,其值均为字符串列表。</p>
|
||
<p>这很容易使用,但如果你预期要上传巨量字节数据时就不太适合了 --- 在这种情况下,请改用更为灵活的 <code class="xref py py-class docutils literal notranslate"><span class="pre">FieldStorage</span></code> 类。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.7 版更改: </span>增加了 <em>encoding</em> 和 <em>errors</em> 形参。 对于非文件字段,其值现在为字符串列表而非字节串列表。</p>
|
||
</div>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8.8 版更改: </span>增加了 <em>separator</em> 形参。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="cgi.parse_header">
|
||
<code class="sig-prename descclassname">cgi.</code><code class="sig-name descname">parse_header</code><span class="sig-paren">(</span><em class="sig-param">string</em><span class="sig-paren">)</span><a class="headerlink" href="#cgi.parse_header" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>将一个 MIME 标头 (例如 <em class="mailheader">Content-Type</em>) 解析为一个主值和一个参数字典。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="cgi.test">
|
||
<code class="sig-prename descclassname">cgi.</code><code class="sig-name descname">test</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#cgi.test" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>Robust test CGI script, usable as main program. Writes minimal HTTP headers and
|
||
formats all information provided to the script in HTML form.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="cgi.print_environ">
|
||
<code class="sig-prename descclassname">cgi.</code><code class="sig-name descname">print_environ</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#cgi.print_environ" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>以 HTML 格式来格式化 shell 环境。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="cgi.print_form">
|
||
<code class="sig-prename descclassname">cgi.</code><code class="sig-name descname">print_form</code><span class="sig-paren">(</span><em class="sig-param">form</em><span class="sig-paren">)</span><a class="headerlink" href="#cgi.print_form" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>以 HTML 格式来格式化表单。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="cgi.print_directory">
|
||
<code class="sig-prename descclassname">cgi.</code><code class="sig-name descname">print_directory</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#cgi.print_directory" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>以 HTML 格式来格式化当前目录。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="cgi.print_environ_usage">
|
||
<code class="sig-prename descclassname">cgi.</code><code class="sig-name descname">print_environ_usage</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#cgi.print_environ_usage" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>以 HTML 格式打印有用的环境变量列表(供 CGI 使用)。</p>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="caring-about-security">
|
||
<span id="cgi-security"></span><h2>对于安全性的关注<a class="headerlink" href="#caring-about-security" title="永久链接至标题">¶</a></h2>
|
||
<p id="index-1">There's one important rule: if you invoke an external program (via the
|
||
<a class="reference internal" href="os.html#os.system" title="os.system"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.system()</span></code></a> or <a class="reference internal" href="os.html#os.popen" title="os.popen"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.popen()</span></code></a> functions. or others with similar
|
||
functionality), make very sure you don't pass arbitrary strings received from
|
||
the client to the shell. This is a well-known security hole whereby clever
|
||
hackers anywhere on the Web can exploit a gullible CGI script to invoke
|
||
arbitrary shell commands. Even parts of the URL or field names cannot be
|
||
trusted, since the request doesn't have to come from your form!</p>
|
||
<p>为了安全起见,如果你必须将从表单获取的字符串传给 shell 命令,你应当确保该字符串仅包含字母数字类字符、连字符、下划线和句点。</p>
|
||
</section>
|
||
<section id="installing-your-cgi-script-on-a-unix-system">
|
||
<h2>在 Unix 系统上安装你的 CGI 脚本<a class="headerlink" href="#installing-your-cgi-script-on-a-unix-system" title="永久链接至标题">¶</a></h2>
|
||
<p>请阅读你的 HTTP 服务器的文档并咨询你所用系统的管理员来找到 CGI 脚本应当安装到哪个目录;通常是服务器目录树中的 <code class="file docutils literal notranslate"><span class="pre">cgi-bin</span></code> 目录。</p>
|
||
<p>请确保你的脚本可被“其他人”读取和执行;Unix 文件模式应为八进制数 <code class="docutils literal notranslate"><span class="pre">0o755</span></code> (使用 <code class="docutils literal notranslate"><span class="pre">chmod</span> <span class="pre">0755</span> <span class="pre">filename</span></code>)。 请确保脚本的第一行包含 <code class="docutils literal notranslate"><span class="pre">#!</span></code> 且位置是从第 1 列开始,后面带有 Python 解释器的路径名,例如:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/usr/local/bin/python</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>请确保该 Python 解释器存在并且可被“其他人”执行。</p>
|
||
<p>请确保你的脚本需要读取或写入的任何文件都分别是“其他人”可读取或可写入的 --- 它们的模式应为可读取 <code class="docutils literal notranslate"><span class="pre">0o644</span></code> 或可写入 <code class="docutils literal notranslate"><span class="pre">0o666</span></code>。 这是因为出于安全理由,HTTP 服务器是作为没有任何特殊权限的 "nobody" 用户来运行脚本的。 它只能读取(写入、执行)任何人都能读取(写入、执行)的文件。 执行时的当前目录(通常为服务器的 cgi-bin 目录)和环境变量集合也与你在登录时所得到的不同。 特别地,不可依赖于 shell 的可执行文件搜索路径 (<span class="target" id="index-9"></span><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PATH</span></code>) 或 Python 模块搜索路径 (<span class="target" id="index-10"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONPATH"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHONPATH</span></code></a>) 的任何相关设置。</p>
|
||
<p>如果你需要从 Python 的默认模块搜索路径之外的目录载入模块,你可以在导入其他模块之前在你的脚本中改变路径。 例如:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="s2">"/usr/home/joe/lib/python"</span><span class="p">)</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="s2">"/usr/local/lib/python"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>(在此方式下,最后插入的目录将最先被搜索!)</p>
|
||
<p>针对非 Unix 系统的指导会有所变化;请查看你的 HTTP 服务器的文档(通常会有关于 CGI 脚本的部分)。</p>
|
||
</section>
|
||
<section id="testing-your-cgi-script">
|
||
<h2>测试你的 CGI 脚本<a class="headerlink" href="#testing-your-cgi-script" title="永久链接至标题">¶</a></h2>
|
||
<p>很不幸,当你在命令行中尝试 CGI 脚本时它通常会无法运行,而能在命令行中完美运行的脚本则可能会在运行于服务器时神秘地失败。 但有一个理由使你仍然应当在命令行中测试你的脚本:如果它包含语法错误,Python 解释器将根本不会执行它,而 HTTP 服务器将很可能向客户端发送令人费解的错误信息。</p>
|
||
<p>假定你的脚本没有语法错误,但它仍然无法起作用,你将别无选择,只能继续阅读下一节。</p>
|
||
</section>
|
||
<section id="debugging-cgi-scripts">
|
||
<h2>调试 CGI 脚本<a class="headerlink" href="#debugging-cgi-scripts" title="永久链接至标题">¶</a></h2>
|
||
<p id="index-4">First of all, check for trivial installation errors --- reading the section
|
||
above on installing your CGI script carefully can save you a lot of time. If
|
||
you wonder whether you have understood the installation procedure correctly, try
|
||
installing a copy of this module file (<code class="file docutils literal notranslate"><span class="pre">cgi.py</span></code>) as a CGI script. When
|
||
invoked as a script, the file will dump its environment and the contents of the
|
||
form in HTML form. Give it the right mode etc, and send it a request. If it's
|
||
installed in the standard <code class="file docutils literal notranslate"><span class="pre">cgi-bin</span></code> directory, it should be possible to
|
||
send it a request by entering a URL into your browser of the form:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>http://yourhostname/cgi-bin/cgi.py?name=Joe+Blow&addr=At+Home
|
||
</pre></div>
|
||
</div>
|
||
<p>如果此操作给出类型为 404 的错误,说明服务器找不到此脚本 -- 也许你需要将它安装到不同的目录。 如果它给出另一种错误,说明存在安装问题,你应当解决此问题才能继续操作。 如果你得到一个格式良好的环境和表单内容清单(在这个例子中,应当会列出的有字段 "addr" 值为 "At Home" 以及 "name" 值为 "Joe Blow"),则说明 <code class="file docutils literal notranslate"><span class="pre">cgi.py</span></code> 脚本已正确安装。 如果你为自己的脚本执行了同样的过程,现在你应该能够调试它了。</p>
|
||
<p>下一步骤可以是在你的脚本中调用 <a class="reference internal" href="#module-cgi" title="cgi: Helpers for running Python scripts via the Common Gateway Interface."><code class="xref py py-mod docutils literal notranslate"><span class="pre">cgi</span></code></a> 模块的 <a class="reference internal" href="test.html#module-test" title="test: Regression tests package containing the testing suite for Python."><code class="xref py py-func docutils literal notranslate"><span class="pre">test()</span></code></a> 函数:用这一条语句替换它的主代码</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">cgi</span><span class="o">.</span><span class="n">test</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这将产生从安装 <code class="file docutils literal notranslate"><span class="pre">cgi.py</span></code> 文件本身所得到的相同结果。</p>
|
||
<p>当某个常规 Python 脚本触发了未处理的异常,(无论出于什么原因:模块名称出错、文件无法打开等),Python 解释器就会打印出一条完整的跟踪信息并退出。在 CGI 脚本触发异常时,Python 解释器依然会如此,但最有可能的是,跟踪信息只会停留在某个 HTTP 服务日志文件中,或者被完全丢弃。</p>
|
||
<p>幸运的是,只要执行 <em>某些</em> 代码,就可以利用 <a class="reference internal" href="cgitb.html#module-cgitb" title="cgitb: Configurable traceback handler for CGI scripts."><code class="xref py py-mod docutils literal notranslate"><span class="pre">cgitb</span></code></a> 模块将跟踪信息发送给浏览器。 如果你还没有这样做过,只需添加以下几行代码:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">cgitb</span>
|
||
<span class="n">cgitb</span><span class="o">.</span><span class="n">enable</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>然后再运行一下看;发生问题时应能看到详细的报告,或许能让崩溃的原因更清晰一些。</p>
|
||
<p>如果怀疑是 <a class="reference internal" href="cgitb.html#module-cgitb" title="cgitb: Configurable traceback handler for CGI scripts."><code class="xref py py-mod docutils literal notranslate"><span class="pre">cgitb</span></code></a> 模块导入的问题,可以采用一个功能更强的方法(只用到内置模块):</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Content-Type: text/plain"</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">()</span>
|
||
<span class="o">...</span><span class="n">your</span> <span class="n">code</span> <span class="n">here</span><span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这得靠 Python 解释器来打印跟踪信息。输出的类型为纯文本,不经过任何 HTML 处理。如果代码正常,则客户端会显示原有的 HTML。如果触发了异常,很可能在输出前两行后会显示一条跟踪信息。因为不会继续进行 HTML 解析,所以跟踪信息肯定能被读到。</p>
|
||
</section>
|
||
<section id="common-problems-and-solutions">
|
||
<h2>常见问题和解决方案<a class="headerlink" href="#common-problems-and-solutions" title="永久链接至标题">¶</a></h2>
|
||
<ul class="simple">
|
||
<li><p>大部分 HTTP 服务器会对 CGI 脚本的输出进行缓存,等脚本执行完毕再行输出。这意味着在脚本运行时,不可能在客户端屏幕上显示出进度情况。</p></li>
|
||
<li><p>请查看上述安装说明。</p></li>
|
||
<li><p>请查看 HTTP 服务器的日志文件。(在另一个单独窗口中执行 <code class="docutils literal notranslate"><span class="pre">tail</span> <span class="pre">-f</span> <span class="pre">logfile</span></code> 可能会很有用!)</p></li>
|
||
<li><p>一定要先检查脚本是否有语法错误,做法类似:<code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">script.py</span></code> 。</p></li>
|
||
<li><p>如果脚本没有语法错误,试着在脚本的顶部添加 <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">cgitb;</span> <span class="pre">cgitb.enable()</span></code>。</p></li>
|
||
<li><p>当调用外部程序时,要确保其可被读取。通常这意味着采用绝对路径名------ 在 CGI 脚本中, <span class="target" id="index-11"></span><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PATH</span></code> 的值通常没什么用。</p></li>
|
||
<li><p>在读写外部文件时,要确保其能被 CGI 脚本归属的用户读写:通常是运行网络服务的用户,或由网络服务的 <code class="docutils literal notranslate"><span class="pre">suexec</span></code> 功能明确指定的一些用户。</p></li>
|
||
<li><p>不要试图给 CGI 脚本赋予 set-uid 模式。这在大多数系统上都行不通,出于安全考虑也不应如此。</p></li>
|
||
</ul>
|
||
<p class="rubric">备注</p>
|
||
<dl class="footnote brackets">
|
||
<dt class="label" id="id3"><span class="brackets"><a class="fn-backref" href="#id2">1</a></span></dt>
|
||
<dd><p>请注意,新版的 HTML 规范确实注明了请求字段的顺序,但判断请求是否合法非常繁琐和容易出错,可能来自不符合要求的浏览器,甚至不是来自浏览器。</p>
|
||
</dd>
|
||
</dl>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<h3><a href="../contents.html">目录</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">cgi</span></code> --- 通用网关接口支持</a><ul>
|
||
<li><a class="reference internal" href="#introduction">概述</a></li>
|
||
<li><a class="reference internal" href="#using-the-cgi-module">使用 cgi 模块</a></li>
|
||
<li><a class="reference internal" href="#higher-level-interface">更高层级的接口</a></li>
|
||
<li><a class="reference internal" href="#functions">函数</a></li>
|
||
<li><a class="reference internal" href="#caring-about-security">对于安全性的关注</a></li>
|
||
<li><a class="reference internal" href="#installing-your-cgi-script-on-a-unix-system">在 Unix 系统上安装你的 CGI 脚本</a></li>
|
||
<li><a class="reference internal" href="#testing-your-cgi-script">测试你的 CGI 脚本</a></li>
|
||
<li><a class="reference internal" href="#debugging-cgi-scripts">调试 CGI 脚本</a></li>
|
||
<li><a class="reference internal" href="#common-problems-and-solutions">常见问题和解决方案</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="webbrowser.html"
|
||
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">webbrowser</span></code> --- 方便的Web浏览器控制器</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="cgitb.html"
|
||
title="下一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">cgitb</span></code> --- 用于 CGI 脚本的回溯管理器</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<h3>本页</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">报告 Bug</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.8/Doc/library/cgi.rst"
|
||
rel="nofollow">显示源代码
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>导航</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="总目录"
|
||
>索引</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python 模块索引"
|
||
>模块</a> |</li>
|
||
<li class="right" >
|
||
<a href="cgitb.html" title="cgitb --- 用于 CGI 脚本的回溯管理器"
|
||
>下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="webbrowser.html" title="webbrowser --- 方便的Web浏览器控制器"
|
||
>上一页</a> |</li>
|
||
|
||
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.8.20 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="internet.html" >互联网协议和支持</a> »</li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
|
||
<input type="submit" value="转向" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
<div class="footer">
|
||
© <a href="../copyright.html">版权所有</a> 2001-2024, Python Software Foundation.
|
||
<br />
|
||
This page is licensed under the Python Software Foundation License Version 2.
|
||
<br />
|
||
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
|
||
<br />
|
||
|
||
<br />
|
||
|
||
The Python Software Foundation is a non-profit corporation.
|
||
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
||
<br />
|
||
<br />
|
||
|
||
最后更新于 12月 09, 2024.
|
||
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
|
||
<br />
|
||
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 2.4.4.
|
||
</div>
|
||
|
||
</body>
|
||
</html> |