您好,登录后才能下订单哦!
这篇文章主要为大家展示了“Python中的知识点有哪些”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python中的知识点有哪些”这篇文章吧。
最早的时候,WEB就是一些静态文件。由开发人员通过编辑器直接编辑生成静态的HTML页面,如果要修改WEB页面的内容或布局,就得编辑这些静态的HTML文件。早期的时候就是这么来玩的,是不是让人着实不爽?
由于静态WEB页面无法与用户进行交互(提交表单等操作)。为了解决这一问题,人们开发出了一种称为CGI(Common Gateway Interface)的技术,使用 C/C++
编写。
由于WEB应用的特点是频繁更新,用低级语言非常不适合高效地开发。而脚本语言(JSP、PHP)由于开发效率高,与HTML结合紧密,因此,迅速取代了CGI模式。JSP使用Java编写脚本,而PHP则是开源的脚本语言。
最早的动态页面是CGI实现的,CGI是怎么工作的?当请求某个地址的时候,http服务器会启动一个外部程序,并且把外部程序的输出返回给用户。CGI规范了http和外部程序的通信方式。
输入:通过环境变量
输出:通过标准输出
CGI的缺点:
并发模式是多进程
进程由http服务器管理
基于CGI以上的缺点,由此衍生出了FastCGI技术,把进程管理交给其他服务来处理。http服务器把http协议转化成fastcgi协议,通过socket发送给FastCGI守护进程。这样并发模型变得多种多样,进程管理由FastCGI实现,单一原则。
另一个分支就是由cgi发展的wsgi技术。接下来就看看wsgi。
Web框架的主要关键点:
路由
Request解析
Response封装
Web服务器网关接口(WSGI)是Python Web应用程序框架和Web服务器之间标准接口的规范。
在Python Web应用程序的早期,由于没有统一的标准,将Web应用程序框架连接到Web服务器是不容易的。Python Web应用程序是用于工作的,具体是通过运用现有的CGI、FastCGI或mod_python(Apache)标准之一。这意味着在一个Web服务器上工作的应用程序可能无法在另一个Web服务器上工作。换言之,统一的应用程序与Web服务器之间的互操作性没有了。
WSGI通过在服务器和Web应用框架之间指定一个简单但统一的接口来解决这个问题,从而允许移植Web应用程序。
WSGI指定了两个方面:服务器(或网关)端,以及应用程序或框架端。WSGI请求得到了以下处理:
服务器端执行应用程序,给应用程序提供一个环境和一个回调函数。
应用程序处理请求,并使用所提供的回调函数返回响应给服务器。
流程如下:
wsgi两部分组成:容器,应用。也可以把容器称为网关或服务器。容器实现了协议转换,由http协议到wsgi协议的转换;应用用来处理业务逻辑。
容器和应用怎么通信呢?FastCGI通过socket;wsgi的容器和应用通过函数调用进行通信。什么情况下可以通过函数调用实现通信?同一进程内可以实现函数调用,wsgi的容器和应用是运行在同一进程之中。
常用的wsgi容器:gunicorn,uWSGI。
说了这么多,还是看个简单的例子吧,看看wsgi是如何工作的。接下来实现一个helloworld的程序。
wsgi application应该是一个callable对象。函数是可调用的,如果一个类有__call__
方法,也是可调用的。
wsgi函数的书写有一定的要求,它的函数签名一般如下,比较固定:
def application(environ, start_response): ''' # 函数传入的参数是有规定的: # environ:environ变量是从服务器传递到应用程序的环境变量的字典,如请求内容等; # 由公共网关接口(CGI)规范定义。WSGI在其规范中规定了一些环境变量受托者 # start_response:一个可调用对象,其提供一个从服务器端到应用程序端的回调,从而开启服务器端的 # 响应处理。它必须有两个位置参数。第一个应该是具有整型状态吗的状态字符串,第二个是一个(header_name, header_value)列表,其是描述HTTP头响应的元组。 ''' pass
上述函数传入的参数是有规定的:
environ
:environ
变量是从服务器传递到应用程序的环境变量的字典,如请求内容等;由公共网关接口(CGI)规范定义。WSGI在其规范中规定了一些环境变量受托者
start_response
:一个可调用对象,其提供一个从服务器端到应用程序端的回调,从而开启服务器端的响应处理。它必须有两个位置参数。第一个应该是具有整型状态吗的状态字符串,第二个是一个(header_name, header_value
)列表,其是描述HTTP头响应的元组。
要了解更多的WSGI规范,可以看看PEP 3333提案。
开始写:
def application(environ, start_response): body = 'hello world' status = '200 OK' headers = [ ('content-type', 'text/plain'), ('content-length', str(len(body))) ] start_response(status, headers) return [body.encode()] # 以上代码只有应用,没有容器; if __name__ == '__main__': # 引入wsgi容器 from wsgiref.simple_server import make_server server = make_server('0.0.0.0', 8000, application) try: server.serve_forever() except KeyboardInterrupt: server.shutdown()
运行以上代码,并在浏览器上进行访问:
[lavenliu@VM_113_230_centos 12-web]$ python wsgi01.py 183.192.25.121 - - [13/Oct/2018 18:48:08] "GET / HTTP/1.1" 200 11 183.192.25.121 - - [13/Oct/2018 18:48:09] "GET /favicon.ico HTTP/1.1" 200 11 183.192.25.121 - - [13/Oct/2018 18:48:09] "GET /favicon.ico HTTP/1.1" 200 11
也可以通过curl命令行工具进行访问:
curl -XPOST http://127.0.0.1:8000 -d '{"a": 1}'
接下来使用gunicorn容器来运行上述代码:
# 首先安装gunicorn pip install gunicorn # 接着运行wsgi01.py的application应用 [lavenliu@VM_113_230_centos 12-web]$ gunicorn -b 0.0.0.0 wsgi01:application [2018-10-13 18:55:38 +0800] [18359] [INFO] Starting gunicorn 19.6.0 [2018-10-13 18:55:38 +0800] [18359] [INFO] Listening at: http://0.0.0.0:8000 (18359) [2018-10-13 18:55:38 +0800] [18359] [INFO] Using worker: sync [2018-10-13 18:55:38 +0800] [18397] [INFO] Booting worker with pid: 18397
通常在开发的时候,使用wsgiref就行了,如果在生产中,可以使用第三方的wsgi容器。
上面的代码中,如果想看environ中的内容,可以在上述代码中添加如下的代码:
for k, v in environ.items(): print('{} => {}'.format(k, v)) # 完整的代码如下: # coding: utf-8 def application(environ, start_response): for k, v in environ.items(): print('{} => {}'.format(k, v)) body = 'hello world' status = '200 OK' headers = [ ('content-type', 'text/plain'), ('content-length', str(len(body))) ] start_response(status, headers) return [body.encode()] # 以上只有应用代码,没有容器 if __name__ == '__main__': from wsgiref.simple_server import make_server server = make_server('0.0.0.0', 8000, application) try: server.serve_forever() except KeyboardInterrupt: server.shutdown()
如果再次运行代码,会有如下的输出:
wsgi.input => <gunicorn.http.body.Body object at 0x7fe20286c198> HTTP_ACCEPT_ENCODING => gzip, deflate HTTP_ACCEPT_LANGUAGE => zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 SERVER_PORT => 8000 RAW_URI => / REMOTE_PORT => 16252 HTTP_USER_AGENT => Mozilla/5.0 (Windows NT 6.3; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0 wsgi.file_wrapper => <class 'gunicorn.http.wsgi.FileWrapper'> REMOTE_ADDR => 183.192.25.121 wsgi.version => (1, 0) wsgi.url_scheme => http HTTP_HOST => 115.159.125.96:8000 wsgi.multithread => False HTTP_ACCEPT => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 wsgi.multiprocess => False QUERY_STRING => SERVER_SOFTWARE => gunicorn/19.6.0 SERVER_PROTOCOL => HTTP/1.1 PATH_INFO => / HTTP_CONNECTION => keep-alive REQUEST_METHOD => GET wsgi.run_once => False wsgi.errors => <gunicorn.http.wsgi.WSGIErrorsWrapper object at 0x7fe20286c1d0> SERVER_NAME => 0.0.0.0 HTTP_CACHE_CONTROL => max-age=0 SCRIPT_NAME => gunicorn.socket => <socket.socket fd=10, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('10.105.113.230', 8000), raddr=('183.192.25.121', 16252)>
environ中有一个QUERY_STRING的key,我们可以打印该信息:
[lavenliu@VM_113_230_centos 12-web]$ cat wsgi01.py # coding: utf-8 def application(environ, start_response): print(environ.get('QUERY_STRING')) body = 'hello world' status = '200 OK' headers = [ ('content-type', 'text/plain'), ('content-length', str(len(body))) ] start_response(status, headers) return [body.encode()] # 以上只有应用代码,没有容器 if __name__ == '__main__': from wsgiref.simple_server import make_server server = make_server('0.0.0.0', 8000, application) try: server.serve_forever() except KeyboardInterrupt: server.shutdown()
在浏览器的URL地址栏里输入:
http://115.159.125.96:8000?name=lavenliu&age=25
运行效果如下:
[lavenliu@VM_113_230_centos 12-web]$ gunicorn -b 0.0.0.0 wsgi01:application [2018-10-13 19:15:36 +0800] [20609] [INFO] Starting gunicorn 19.6.0 [2018-10-13 19:15:36 +0800] [20609] [INFO] Listening at: http://0.0.0.0:8000 (20609) [2018-10-13 19:15:36 +0800] [20609] [INFO] Using worker: sync [2018-10-13 19:15:36 +0800] [20647] [INFO] Booting worker with pid: 20647 name=lavenliu&age=25 # 获得的来自客户端的输入
上面的输出中,
name=lavenliu&age=25 # 获得的来自客户端的输入
接下来就是解析来自客户端的输入,解析这件事也不是很困难,不过有标准库来处理这个解析的工作,引入标准库:
from urllib.parse import parse_qs from html import escape parse_qs('name=lavenliu&age=25') # 返回的value是列表,因为有可能key有同名的
执行结果如下:
{'age': ['25'], 'name': ['lavenliu']}
接下来的代码如下:
[lavenliu@VM_113_230_centos 12-web]$ cat wsgi02.py # coding: utf-8 from urllib.parse import parse_qs from html import escape def application(environ, start_response): params = parse_qs(environ.get('QUERY_STRING')) name = params.get('name', ['anon'])[0] body = 'hello {}'.format(name) # 如果用户在浏览器里输入非法的东东时,可能会有问题 status = '200 OK' headers = [ ('content-type', 'text/html'), ('content-length', str(len(body))) ] start_response(status, headers) return [body.encode()] # 以上只有应用代码,没有容器 if __name__ == '__main__': from wsgiref.simple_server import make_server server = make_server('0.0.0.0', 8001, application) try: server.serve_forever() except KeyboardInterrupt: server.shutdown()
如果用户在浏览器这样输入,就有可能有问题:
http://115.159.125.96:8001?name=<script type='text/javascript'>alert('f**k it')</script> # chrome浏览器则没有问题,它会检测到这个输入有问题;如果在IE6上可能就会执行上述代码。 Navigated to http://115.159.125.96:8001/?%3Cscript%20type=%27text/javascript%27%3Ealert(%27f**k%20it%27)%3C/script%3E ?name=<script type='text/javascript'>alert('f**k it')</script>:1 The XSS Auditor refused to execute a script in 'http://115.159.125.96:8001/?name=%3Cscript%20type=%27text/javascript%27%3Ealert(%27f**k%20it%27)%3C/script%3E' because its source code was found within the request. The auditor was enabled as the server sent neither an 'X-XSS-Protection' nor 'Content-Security-Policy' header. Navigated to http://115.159.125.96:8001/?name=%3Cscript%20type=%27text/javascript%27%3Ealert(%27f**k%20it%27)%3C/script%3E # 在火狐浏览器就能通过,不会报错 # IE11版本则没有这个问题
以上是“Python中的知识点有哪些”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。