Python3 CGI编程实现教程

一、背景说明

虽然很久以前就听说“早期的网站很多通过cgi形式实现”、“C++可通过CGI形式编写网页”,日积月累对CGI也有了一些概念,但一直没真正见过一个实际运行的CGI网站,总归还是有些底气不足。

上周在菜鸟教程上看到有CGI的编程实现所以就模仿实现一下,而过程中发现不能成功运行(其实是自己的未指定脚本处理shell的问题),然后又百度其他资料看到实现方式五花八门不是人云亦云就是实现很不规范,所以自己记录一下。

本文实现环境:Ubuntu 16.04 + Python 3.7 + apache2

二、Ubuntu上的apache2配置

2.1 apache2配置文件形式

Ubuntu(严谨点应该说Dibian)上apache的配置文件在/etc/apache2的目录,我们先来看其目录结构,如下:

xxx-available文件夹表示当前apache2支持的功能,对应的xxx-enabled表示启用的功能;xxx-enabled下的文件一般是xxx-available下的文件的软链接。

其中magic定义的是一些MIME的东西(?),envvars定义一些供其他配置文件使用的变量,这两个一般不用我们修改来看我们需要修改的:

/etc/apache2/
|-- apache2.conf    # 该文件通过IncludeOptional包含以下(各目录中的)配置文件
|       `--  ports.conf    # 该文件主要配置监听端口
|-- mods-enabled     # 该目录下的文件是针对某个模块的配置
|       |-- *.load   # .load文件一般是用LoadModule命令加载模块对应的.so文件
|       `-- *.conf   # .conf文件一般是同名.load文件加载的模块的本身需要的配置,一般不用我们管
|-- conf-enabled     # 该目录下的文件一般是针对某项功能的配置
|       `-- *.conf
`-- sites-enabled    # 该目录下的文件用于配置VirtualHost
        `-- *.conf

apache被分成这么多配置文件,是为了让我们方便地知道某项功能对应的配置功是什么;当然对于不熟悉的人则可能感觉到的不是方便而是复杂,此时就要知道这只是一种约定的组织形式而并不是语法上的强制,所以你要所有配置全都一把写在apache2.conf这文件中也是可以的(但注意apache2为先配置先生效后配置不生效原则,如果IncludeOptional在前且已配置某项的值那你在apache2.conf追加的该项值会不生效)。

2.2 apache2启停功能配置操作

从上节的介绍中,我们可以总结出想启用某项功能就在xxx-enabled目录下,创建指向该功能在xxx-available目录下相应文件的软链接;要停用某项功能就删除该功能在xxx-enable目录下相应的软链接。

这操作是可行的,但Ubuntu还直接提供了命令来实现该功能,这可以免除我们切换目录、忘记软链接命令书写格式、遗漏链接等困挠。

mod对应的启停用使令是a2enmod/a2dismod,conf对应的启停用命令是a2enconf/a2disconf,site对应的启停用命令是a2ensite/a2dissite。

比如我们这里想启用停用cgi支持功能对应的命令就是:

# cgi和cgid这两个模块的区别是什么我还不太懂,似乎其实只用cgid就可以了(?)
# 启用,cgi、cgid这两个名字是mods-available目录下的文件的名字
sudo a2enmod cgi cgid
# 停用,cgi、cgid这两个名字是mods-enabled目录下要删除掉的软链接的名字
sudo a2dismod cgi cgid

可能有小伙伴还是感觉没有很方便啊,我还是得到mods-available或mods-enabled下看文件的名字;那其实还有另外的写法,你可以先不带要启用/停用的功能的名字,然后该命令就会列出当前所有可启用/停用的功能的名字,此时你再输入想要启用/停用的功能的名字即可,如下图:

三、Python3 CGI编程实现

3.1 apache2配置支持cgi

总结第二大节知识,使用以下命令启用:

# 启用模块支持。还是那句话我暂时没懂cgi和cgid的区别,所以索性两个都启用
sudo a2enmod cgi cgid
# 启用cgi的默认配置。
sudo a2enconf serve-cgi-bin
# 重启apache使用置生效
sudo systemctl restart apache2

3.2 针对性改造

这里的针对性改造指两点,一是我们前面只是启动了cgi我们还没给apache指出要处理什么语言的cgi,二是我们想指定cgi文件的目录为/var/www/cgi-bin。

我们先到/etc/apache2/conf-enabled目录下查看serve-cgi-bin.conf的配置,默认如下:

<IfModule mod_alias.c>
        <IfModule mod_cgi.c>
                Define ENABLE_USR_LIB_CGI_BIN
        </IfModule>

        <IfModule mod_cgid.c>
                Define ENABLE_USR_LIB_CGI_BIN
        </IfModule>

        <IfDefine ENABLE_USR_LIB_CGI_BIN>
                ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
                <Directory "/usr/lib/cgi-bin">
                        AllowOverride None
                        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                        Require all granted
                </Directory>
        </IfDefine>
</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

可以看到一是没有配置处理文件,二是设置的文件夹是/usr/lib/cgi-bin/。我们使用"AddHandler cgi-script .cgi .py"指定cgi指定扩展名为.cgi和.py的文件(一般不管什么语言写的都应保存成.cgi但对于pytho也允许保存成习惯的.py),另使用“ScriptAlias /cgi-bin/ /var/www/cgi-bin/”指定遇到路径为“/cgi-bin/”的url就转向“/var/www/cgi-bin/”目录下找文件,最终修改如下:

<IfModule mod_alias.c>
        <IfModule mod_cgi.c>
                Define ENABLE_USR_LIB_CGI_BIN
        </IfModule>

        <IfModule mod_cgid.c>
                Define ENABLE_USR_LIB_CGI_BIN
        </IfModule>

        <IfDefine ENABLE_USR_LIB_CGI_BIN>
                ScriptAlias /cgi-bin/ /var/www/cgi-bin/
                <Directory "/var/www/cgi-bin/">
                        AllowOverride None
                        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                        Require all granted
                        AddHandler cgi-script .cgi .py
                </Directory>
        </IfDefine>
</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

3.3 python文件编写

注意两点:

一是开头的#!指定文件解析shell不可少且shell要改成自己python所在路径(否则报错“End of script output before headers:”),因为我们虽然指定了cgi处理.py文件,但本质上apache还是不懂.py应该使用哪个shell去处理.py文件。

二是大多数教程都是上来直接写print(),我这里特地写成了一个方法的形式,主要是为了强调cgi最终就是python helloworld.py这么运行的,你最终输出一个html响应就行,并不需要你上来就print()。

# 创建/var/www/cgi-bin/目录
sudo mkdir /var/www/cgi-bin/
# 创建helloworld.py文件并写入内容
# 我不清楚为什么sudo直接cat写入会提示Permission denied所以搞这么麻烦
sudo touch /var/www/cgi-bin/helloworld.py
sudo chmod 777 /var/www/cgi-bin/helloworld.py
sudo cat > /var/www/cgi-bin/helloworld.py << EOF
#!/opt/miniconda3/bin/python

def main():
        print ("Content-type:text/html")
        print ()                             # 空行,告诉服务器结束头部
        print (‘<html>‘)
        print (‘<head>‘)
        print (‘<meta charset="utf-8">‘)
        print (‘<title>Hello Word - My First CGI Programe !</title>‘)
        print (‘</head>‘)
        print (‘<body>‘)
        print (‘<h2>Hello Word! This is my first CGI programe !</h2>‘)
        print (‘</body>‘)
        print (‘</html>‘)

main()
EOF
# 如果自使使用vi写入的文件那么写完后记得给文件添加可执行权限

3.4 运行效果演示

由于在前边做了很多配置,为了以防万一建议在访问前重启一把apache:

sudo systemctl restart apache2

运行效果如下:

3.5 运行过程分析【可选】

请求-响应数据包过程如下:

我们在/var/www/cgi-bin目录下新建一个error.py文件,写入以下内容并保存(主要是没有指定shell那一行运行会报错):

def main():
        print("Content-type:text/html")
        print()                             # 空行,告诉服务器结束头部
        print(‘<html>‘)
        print(‘<head>‘)
        print(‘<meta charset="utf-8">‘)
        print(‘<title>Hello Word - My First CGI Programe !</title>‘)
        print(‘</head>‘)
        print(‘<body>‘)
        print(‘<h2>Hello Word! This is my first CGI programe !</h2>‘)
        print(‘</body>‘)
        print(‘</html>‘)

main()

重启apache后访问两次error.py页面两次,然后查看错误日志(默认是/var/log/apache2/error.log)末尾的内容,如果没有意外应该是如下的两个报错;报错没有什么问题,问题是我们可以看到两次访问报错的进程id是不一样的,这就认证了cgi每次都重新启动一个进程的说法(本质差不多和自己手动运行python文件差不多)。

参考:

https://www.runoob.com/python3/python3-cgi-programming.html

原文地址:https://www.cnblogs.com/lsdb/p/11287448.html

时间: 2024-10-05 02:18:12

Python3 CGI编程实现教程的相关文章

吴裕雄--python编程:CGI编程

什么是CGI CGI 目前由NCSA维护,NCSA定义CGI如下: CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如:HTTP服务器,提供同客户端HTML页面的接口. 网页浏览 为了更好的了解CGI是如何工作的,我们可以从在网页上点击一个链接或URL的流程: 1.使用你的浏览器访问URL并连接到HTTP web 服务器. 2.Web服务器接收到请求信息后会解析URL,并查找访问的文件在服务器上是否存在,如果存在返回文件的内容,否则返回错误信

CGI编程学习

@CGI编程学习 目录(?)[+] 一.基本原理 CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口.通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端. 组成CGI通信系统的是两部分:一部分是html页面,就是在用户端浏览器上显示的页面.另一部分则是运行在服务器上的Cgi程序. 它们之间的通讯方式如下图: 服务器 客户端 CGI程序 HTTP通信 标准输入输出 (环境

Python3 函数式编程(高阶函数)

这一次主要是学习了一下Python3函数式编程思想,介绍了3个代表性高阶函数:map(), reduce(), filter().像 sorted() 其实也是高阶函数,可以接受函数作为参数.这篇学习笔记中编写了大量高阶函数,同时介绍了Python中的闭包,装饰器.这些思想和方法很美妙,我受益匪浅.当然这些都需要进一步运用和学习. 运行环境:Python3.6 + Jupyter notebook .caret, .dropup > .btn > .caret { border-top-col

Perl CGI编程

http://www.runoob.com/perl/perl-cgi-programming.html 什么是CGI CGI 目前由NCSA维护,NCSA定义CGI如下: CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如:HTTP服务器,提供同客户端HTML页面的接口. 网页浏览 为了更好的了解CGI是如何工作的,我们可以从在网页上点击一个链接或URL的流程: 1.使用你的浏览器访问URL并连接到HTTP web 服务器. 2.Web服务

CGI编程

一.CGI编程 http://www.w3cschool.cc/python/python-cgi.html(里面实例很详细) 简单编程过程: 1.服务器的结构创建: 首先要一个web根目录(这里是web-app文件夹),所有的CGI或者py文件要存放在cgi-bin目录下,html则不能存放在该目录下. 2.启动python的web服务器(适合简单的测试) python -m CGIHTTPServe 3.编辑脚本 [[email protected] cgi-bin]# cat test.c

Vbs 脚本编程简明教程之一

-为什么要使用 Vbs ? 在 Windows 中,学习计算机操作也许很简单,但是很多计算机工作是重复性劳动,例如你每周也许需要对一些计算机文件进行复制.粘贴.改名.删除,也许你每天启动 计算机第一件事情就是打开 WORD ,切换到你喜爱的输入法进行文本编辑,同时还要播放优美的音乐给工作创造一个舒心的环境,当然也有可能你经常需要对文本中的某 些数据进行整理,把各式各样的数据按照某种规则排列起来--.这些事情重复.琐碎,使人容易疲劳. 第三方软件也许可以强化计算机的某些功能,但是解决这些重复劳动往

Net并行编程高级教程--Parallel

Net并行编程高级教程--Parallel 一直觉得自己对并发了解不够深入,特别是看了<代码整洁之道>觉得自己有必要好好学学并发编程,因为性能也是衡量代码整洁的一大标准.而且在<失控>这本书中也多次提到并发,不管是计算机还是生物都并发处理着各种事物.人真是奇怪,当你关注一个事情的时候,你会发现周围的事物中就常出现那个事情.所以好奇心驱使下学习并发.便有了此文. 一.理解硬件线程和软件线程 多核处理器带有一个以上的物理内核--物理内核是真正的独立处理单元,多个物理内核使得多条指令能够

几种语言的CGI编程

为了了解PHP.JSP.ASP出现之前人们写网站的方法,洒家研究了一波CGI,使用C.Python.batch.shell script语言写了几个简单的网页. CGI即通用网关接口,指web服务器调用编程语言编写的程序的一个接口.洒家用的是Apache的CGI,QUERY_STRING.REMOTE_ADDR.REQUEST_URI等参数是通过环境变量传递给CGI程序的,请求主体(POST数据)作为CGI程序的标准输入(stdin),而CGI程序的标准输出(stdout)作为HTTP响应的部分

PHP面向对象(OOP)编程完全教程

转自:http://blog.snsgou.com/post-41.html 面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行PHP的高级编程,对于提高PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们就通过实例来说明使用PHP的OOP进行编程的实际意义和应用方法. 我们通常在做一个有数据库后台的网站的时候,都会考虑到程序需要适用于不同的应用环境.和其他编程语言有所不同的是,在PHP中,操作数据库的是一系列的具体功能函数(如