从零开始开发一个 Web 服务器(2)

从零开始:编写一个Web服务器---了解Web服务器 从零开始:编写一个Web服务器---1.了解Web服务器什么是Web Server?用户如何与Web Server通信HTTP协议的基本过程(应用层)TCP协议的基本过程(运输层) 在看完Linux网络编程之后,突然想做一个有挑战性的项目,实现一个高性能的Web服务器。于是我萌生了一边自己学着写服务器,一边详细的写出一个Web服务器的整体流程。 本系列文章推荐的参考书有:《Linux高性能服务器编程(游双)》 《APUE》《CSAPP》 阅读本系列文章不需要全部弄懂这几本书,只需要有一个大概框架即可,参考 阅读详情

后台回复【入门资料】

送你十本Python电子书

640

文 | ruslanspivak 译 | EarlGrey

在上文中,我给大家留了一个问题:如何在不对服务器代码作任何修改的情况下,通过该服务器运行Djando应用、Flask应用和Pyramid应用,同时满足这些不同网络框架的要求?读完这篇文章,你就可以回答这个问题了。

以前,你选择的Python网络框架将会限制所能够使用的网络服务器,反之亦然。如果框架和服务器在设计时就是可以相互匹配的,那你就不会面临这个问题:

640?wx_fmt=jpeg

但是如果你试图将设计不相匹配的服务器与框架相结合,那么你肯定就会碰到下面这张图所展示的这个问题:

640?wx_fmt=jpeg

这就意味着,你基本上只能使用能够正常运行的服务器与框架组合,而不能选择你希望使用的服务器或框架。

那么,你怎样确保可以在不修改网络服务器代码或网络框架代码的前提下,使用自己选择的服务器,并且匹配多个不同的网络框架呢?为了解决这个问题,就出现了Python Web服务器网关接口(Python Web Server Gateway Interface,简称“WSGI”)。

640?wx_fmt=jpeg

WSGI的出现,让开发者可以将网络框架与网络服务器的选择分隔开来,不再相互限制。现在,你可以真正地将不同的网络服务器与网络开发框架进行混合搭配,选择满足自己需求的组合。例如,你可以使用Gunicorn或Nginx/uWSGI或Waitress服务器来运行Django、Flask或Pyramid应用。正是由于服务器和框架均支持WSGI,才真正得以实现二者之间的自由混合搭配。

所以,WSGI就是我在上一篇文章中所留问题的答案。你的网络服务器必须实现一个服务器端的WSGI接口,而目前所有现代Python网络框架都已经实现了框架端的WSGI接口,这样开发者不需要修改服务器的代码,就可以支持某个网络框架。

网络服务器和网络框架支持WSGI协议,不仅让应用开发者选择符合自己需求的组合,同时也有利于服务器和框架的开发者,因为他们可以将注意力集中在自己擅长的领域,而不是相互倾轧。其他编程语言也拥有类似的接口:例如Java的Servlet API和Ruby的Rack。

口说无凭,我猜你肯定在想:“无代码无真相!”既然如此,我就在这里给出一个非常简单的WSGI服务器实现:

# Tested with Python 2.7.9, Linux & Mac OS X	
import socket	
import StringIO	
import sys	
class WSGIServer(object):	
    address_family = socket.AF_INET	
    socket_type = socket.SOCK_STREAM	
    request_queue_size = 1	
    def __init__(self, server_address):	
        # Create a listening socket	
        self.listen_socket = listen_socket = socket.socket(	
            self.address_family,	
            self.socket_type	
        )	
        # Allow to reuse the same address	
        listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)	
        # Bind	
        listen_socket.bind(server_address)	
        # Activate	
        listen_socket.listen(self.request_queue_size)	
        # Get server host name and port	
        host, port = self.listen_socket.getsockname()[:2]	
        self.server_name = socket.getfqdn(host)	
        self.server_port = port	
        # Return headers set by Web framework/Web application	
        self.headers_set = []	
    def set_app(self, application):	
        self.application = application	
    def serve_forever(self):	
        listen_socket = self.listen_socket	
        while True:	
            # New client connection	
            self.client_connection, client_address = listen_socket.accept()	
            # Handle one request and close the client connection. Then	
            # loop over to wait for another client connection	
            self.handle_one_request()	
    def handle_one_request(self):	
        self.request_data = request_data = self.client_connection.recv(1024)	
        # Print formatted request data a la 'curl -v'	
        print(''.join(	
            '< {line}\n'.format(line=line)	
            for line in request_data.splitlines()	
        ))	
        self.parse_request(request_data)	
        # Construct environment dictionary using request data	
        env = self.get_environ()	
        # It's time to call our application callable and get	
        # back a result that will become HTTP response body	
        result = self.application(env, self.start_response)	
        # Construct a response and send it back to the client	
        self.finish_response(result)	
    def parse_request(self, text):	
        request_line = text.splitlines()[0]	
        request_line = request_line.rstrip('\r\n')	
        # Break down the request line into components	
        (self.request_method,  # GET	
         self.path,            # /hello	
         self.request_version  # HTTP/1.1	
         ) = request_line.split()	
    def get_environ(self):	
        env = {}	
        # The following code snippet does not follow PEP8 conventions	
        # but it's formatted the way it is for demonstration purposes	
        # to emphasize the required variables and their values	
        #	
        # Required WSGI variables	
        env['wsgi.version']      = (1, 0)	
        env['wsgi.url_scheme']   = 'http'	
        env['wsgi.input']        = StringIO.StringIO(self.request_data)	
        env['wsgi.errors']       = sys.stderr	
        env['wsgi.multithread']  = False	
        env['wsgi.multiprocess'] = False	
        env['wsgi.run_once']     = False	
        # Required CGI variables	
        env['REQUEST_METHOD']    = self.request_method    # GET	
        env['PATH_INFO']         = self.path              # /hello	
        env['SERVER_NAME']       = self.server_name       # localhost	
        env['SERVER_PORT']       = str(self.server_port)  # 8888	
        return env	
    def start_response(self, status, response_headers, exc_info=None):	
        # Add necessary server headers	
        server_headers = [	
            ('Date', 'Tue, 31 Mar 2015 12:54:48 GMT'),	
            ('Server', 'WSGIServer 0.2'),	
        ]	
        self.headers_set = [status, response_headers + server_headers]	
        # To adhere to WSGI specification the start_response must return	
        # a 'write' callable. We simplicity's sake we'll ignore that detail	
        # for now.	
        # return self.finish_response	
    def finish_response(self, result):	
        try:	
            status, response_headers = self.headers_set	
            response = 'HTTP/1.1 {status}\r\n'.format(status=status)	
            for header in response_headers:	
                response += '{0}: {1}\r\n'.format(*header)	
            response += '\r\n'	
            for data in result:	
                response += data	
            # Print formatted response data a la 'curl -v'	
            print(''.join(	
                '> {line}\n'.format(line=line)	
                for line in response.splitlines()	
            ))	
            self.client_connection.sendall(response)	
        finally:	
            self.client_connection.close()	
SERVER_ADDRESS = (HOST, PORT) = '', 8888	
def make_server(server_address, application):	
    server = WSGIServer(server_address)	
    server.set_app(application)	
    return server	
if __name__ == '__main__':	
    if len(sys.argv) < 2:	
        sys.exit('Provide a WSGI application object as module:callable')	
    app_path = sys.argv[1]	
    module, application = app_path.split(':')	
    module = __import__(module)	
    application = getattr(module, application)	
    httpd = make_server(SERVER_ADDRESS, application)	
    print('WSGIServer: Serving HTTP on port {port} ...\n'.format(port=PORT))	
    httpd.serve_forever()

上面的代码比第一部分的服务器实现代码要长的多,但是这些代码实际也不算太长,只有不到150行,大家理解起来并不会太困难。上面这个服务器的功能也更多——它可以运行你使用自己喜欢的框架所写出来的网络应用,无论你选择Pyramid、Flask、Django或是其他支持WSGI协议的框架。

你不信?你可以自己测试一下,看看结果如何。将上述代码保存为 webserver2.py,或者直接从我的Github仓库下载。如果你运行该文件时没有提供任何参数,那么程序就会报错并退出。

$ python webserver2.py	
Provide a WSGI application object as module:callable

上述程序设计的目的,就是运行你开发的网络应用,但是你还需要满足一些它的要求。要运行服务器,你只需要安装Python即可。但是要运行使用Pyramid、Flask和Django等框架开发的网络应用,你还需要先安装这些框架。我们接下来安装这三种框架。我倾向于使用 virtualenv安装。请按照下面的提示创建并激活一个虚拟环境,然后安装这三个网络框架。

$ [sudo] pip install virtualenv	
$ mkdir ~/envs	
$ virtualenv ~/envs/lsbaws/	
$ cd ~/envs/lsbaws/	
$ ls	
bin  include  lib	
$ source bin/activate	
(lsbaws) $ pip install pyramid	
(lsbaws) $ pip install flask	
(lsbaws) $ pip install django

接下来,你需要创建一个网络应用。我们首先创建Pyramid应用。将下面的代码保存为 pyramidapp.py文件,放至 webserver2.py所在的文件夹中,或者直接从我的Github仓库下载该文件:

from pyramid.config import Configurator	
from pyramid.response import Response	
def hello_world(request):	
    return Response(	
        'Hello world from Pyramid!\n',	
        content_type='text/plain',	
    )	
config = Configurator()	
config.add_route('hello', '/hello')	
config.add_view(hello_world, route_name='hello')	
app = config.make_wsgi_app()

现在,你可以通过自己开发的网络服务器来启动上面的Pyramid应用。

(lsbaws) $ python webserver2.py pyramidapp:app	
WSGIServer: Serving HTTP on port 8888 ...

在运行 webserver2.py时,你告诉自己的服务器去加载 pyramidapp模块中的 app可调用对象(callable)。你的服务器现在可以接收HTTP请求,并将请求中转至你的Pyramid应用。应用目前只能处理一个路由(route):/hello。在浏览器的地址栏输入 http://localhost:8888/hello,按下回车键,观察会出现什么情况:

640?wx_fmt=jpeg

你还可以在命令行使用 curl命令,来测试服务器运行情况:

$ curl -v http://localhost:8888/hello	
...

接下来我们创建Flask应用。重复上面的步骤。

from flask import Flask	
from flask import Response	
flask_app = Flask('flaskapp')	
@flask_app.route('/hello')	
def hello_world():	
    return Response(	
        'Hello world from Flask!\n',	
        mimetype='text/plain'	
    )	
app = flask_app.wsgi_app

将上面的代码保存为 flaskapp.py,或者直接从我的Github仓库下载文件,并运行:

(lsbaws) $ python webserver2.py flaskapp:app	
WSGIServer: Serving HTTP on port 8888 ...

然后在浏览器地址栏输入 http://localhost:8888/hello,并按下回车:

640?wx_fmt=jpeg

同样,在命令行使用 curl命令,看看服务器是否会返回Flask应用生成的信息:

$ curl -v http://localhost:8888/hello	
...

这个服务器是不是也能支持Django应用?试一试就知道了!不过接下来的操作更为复杂一些,我建议大家克隆整个仓库,并使用其中的 djangoapp.py文件。下面的代码将一个名叫 helloworld的Django应用添加至当前的Python路径中,然后导入了该项目的WSGI应用。

import sys	
sys.path.insert(0, './helloworld')	
from helloworld import wsgi	
app = wsgi.application

将上面的代码保存为 djangoapp.py,并使用你开发的服务器运行这个Django应用。

(lsbaws) $ python webserver2.py djangoapp:app	
WSGIServer: Serving HTTP on port 8888 ...

同样,在浏览器中输入 http://localhost:8888/hello,并按下回车键:

640?wx_fmt=jpeg

接下来,和前面几次一样,你通过命令行使用 curl命令进行测试,确认了这个Djando应用成功处理了你发出的请求:

$ curl -v http://localhost:8888/hello	
...

你有没有按照上面的步骤测试?你做到了让服务器支持全部三种框架吗?如果没有,请尽量自己动手操作。阅读代码很重要,但这系列文章的目的在于重新开发,而这意味着你需要自己亲自动手。最好是你自己重新输入所有的代码,并确保代码运行结果符合预期。

经过上面的介绍,你应该已经认识到了WSGI的强大之处:它可以让你自由混合搭配网络服务器和框架。WSGI为Python网络服务器与Python网络框架之间的交互提供了一个极简的接口,而且非常容易在服务器端和框架端实现。下面的代码段分别展示了服务器端和框架端的WSGI接口:

def run_application(application):	
    """Server code."""	
    # This is where an application/framework stores	
    # an HTTP status and HTTP response headers for the server	
    # to transmit to the client	
    headers_set = []	
    # Environment dictionary with WSGI/CGI variables	
    environ = {}	
    def start_response(status, response_headers, exc_info=None):	
        headers_set[:] = [status, response_headers]	
    # Server invokes the ‘application' callable and gets back the	
    # response body	
    result = application(environ, start_response)	
    # Server builds an HTTP response and transmits it to the client	
    …	
def app(environ, start_response):	
    """A barebones WSGI app."""	
    start_response('200 OK', [('Content-Type', 'text/plain')])	
    return ['Hello world!']	
run_application(app)

下面给大家解释一下上述代码的工作原理:

  1. 网络框架提供一个命名为 application的可调用对象(WSGI协议并没有指定如何实现这个对象)。

  2. 服务器每次从HTTP客户端接收请求之后,调用 application。它会向可调用对象传递一个名叫 environ的字典作为参数,其中包含了WSGI/CGI的诸多变量,以及一个名为 start_response的可调用对象。

  3. 框架/应用生成HTTP状态码以及HTTP响应报头(HTTP response headers),然后将二者传递至 start_response,等待服务器保存。此外,框架/应用还将返回响应的正文。

  4. 服务器将状态码、响应报头和响应正文组合成HTTP响应,并返回给客户端(这一步并不属于WSGI协议)。

下面这张图直观地说明了WSGI接口的情况:

640?wx_fmt=jpeg

有一点要提醒大家,当你使用上述框架开发网络应用的时候,你处理的是更高层级的逻辑,并不会直接处理WSGI协议相关的要求,但是我很清楚,既然你正在看这篇文章,你一定对框架端的WSGI接口很感兴趣。所以,我们接下来在不使用Pyramid、Flask或Djando框架的前提下,自己开发一个极简的WSGI网络应用/网络框架,并使用WSGI服务器运行该应用:

def app(environ, start_response):	
    """A barebones WSGI application.	
    This is a starting point for your own Web framework :)	
    """	
    status = '200 OK'	
    response_headers = [('Content-Type', 'text/plain')]	
    start_response(status, response_headers)	
    return ['Hello world from a simple WSGI application!\n']

将上述代码保存为 wsgiapp.py文件,或者直接从我的Github仓库下载,然后利用网络服务器运行该应用:

(lsbaws) $ python webserver2.py wsgiapp:app	
WSGIServer: Serving HTTP on port 8888 ...

在浏览器中输入下图中的地址,然后按回车键。结果应该是这样的:

640?wx_fmt=jpeg

你刚刚自己编写了一个极简的WSGI网络框架!太不可思议了。

接下来,我们重新分析服务器返回给客户端的对象。下面这张图展示的是你通过HTTP客户端调用Pyramid应用后,服务器生成的HTTP响应:

640?wx_fmt=jpeg

上图中的响应与你在第一篇中看到的有些类似,但是也有明显不同之处。举个例子,其中就出现了你之前没有看到过的4歌HTTP报头:Content-Type,Content-Length,Date和Server。这些事网络服务器返回的响应对象通常都会包含的报头。不过,这四个都不是必须的。报头的目的是传递有关HTTP请求/响应的额外信息。

既然你已经对WSGI接口有了更深的理解,下面这张图对响应对象的内容进行了更详细的解释,说明了每条内容是如何产生的。

640?wx_fmt=jpeg

到目前为止,我还没有介绍过 environ字典的具体内容,但简单来说,它是一个必须包含着WSGI协议所指定的某些WSGI和CGI变量。服务器从HTTP请求中获取字典所需的值。下面这张图展示的是字典的详细内容:

640?wx_fmt=jpeg

网络框架通过该字典提供的信息,根据指定的路由和请求方法等参数来决定使用哪个视图(views),从哪里读取请求正文,以及如何输出错误信息。

截至目前,你已经成功创建了自己的支持WSGI协议的网络服务器,还利用不同的网络框架开发了多个网络应用。另外,你还自己开发了一个极简的网络框架。本文介绍的内容不可谓不丰富。我们接下来回顾一下WSGI网络服务器如何处理HTTP请求:

  • 首先,服务器启动并加载网络框架/应用提供的 application可调用对象

  • 然后,服务器读取一个请求信息

  • 然后,服务器对请求进行解析

  • 然后,服务器使用请求数据创建一个名叫 environ的字典

  • 然后,服务器以 environ字典和 start_response可调用对象作为参数,调用 application,并获得应用生成的响应正文。

  • 然后,服务器根据调用 application对象后返回的数据,以及 start_response设置的状态码和响应标头,构建一个HTTP响应。

  • 最后,服务器将HTTP响应返回至客户端。

640?wx_fmt=jpeg

以上就是第二部分的所有内容。你现在已经拥有了一个正常运行的WSGI服务器,可以支持通过遵守WSGI协议的网络框架所写的网络应用。最棒的是,这个服务器可以不需要作任何代码修改,就可以与多个网络框架配合使用。

最后,我再给大家留一道思考题:怎样让服务器一次处理多个请求?

原文链接:http://ruslanspivak.com/lsbaws-part2/

译文链接:http://codingpy.com/article/build-a-simple-web-server-part-two/

回复下方「关键词」,获取优质资源

回复关键词「 pybook03」,立即获取主页君与小伙伴一起翻译的《Think Python 2e》电子版

回复关键词「入门资料」,立即获取主页君整理的 10 本 Python 入门书的电子版

回复关键词「m」,立即获取Python精选优质文章合集

回复关键词「book 数字」,将数字替换成 0 及以上数字,有惊喜好礼哦~

推荐阅读

Java编写Web开发框架:从零开始打造一个简易框架! 🏆本文收录于「编程与技术实战」专栏,此专栏涵盖了C/C++编程、人工智能、数据结构、机器学习等技术领域的内容,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!! 阅读详情

相关推荐

从零开始搭建web项目并部署到本地服务器

从零开始搭建web项目并部署到本地服务器需要文件此项目的jdk环境是1.7,服务器用的是tomcat6.0的。如果需要的话可以从以下地址下载。 1. 服务器文件tomcat6.0 2. jdk1.7文件jdk-7u79-windows-i5861. 安装tomcat6.0服务器下载tomcat6.0文件解压。 打开myeclipse,点击window->preferences ->servic

无语的HAHA 1万+

自己动手开发网络服务器(二)

在《自己动手开发网络服务器(一)》中,我给大家留了一个问题:如何在不对服务器代码作任何修改的情况下,通过该服务器运行Djando应用、Flask应用和Pyramid应用,同时满足这些不同网络框架的要求?读完这篇文章,你就可以回答这个问题了。以前,你选择的Python网络框架将会限制所能够使用的网络服务器,反之亦然。如果框架和服务器在设计时就是可以相互匹配的,那你就不会面临这个问题:但是如果你试图将...

追求卓越 1616

如何写一个Web服务器

最近两个月的业余时间在写一个私人项目,目的是在Linux下写一个高性能Web服务器,名字叫Zaver。主体框架和基本功能已完成,还有一些高级功能日后会逐渐增加,代码放在了github。Zaver的框架会在代码量尽量少的情况下接近工业水平,而不像一些教科书上的toy server为了教原理而舍弃了很多原本server应该有的东西,在本篇文章中,我将一步步地阐明Zaver的设计方案和开发过程中遇到的困难以及相应的解决方法

记路 7008

网络开发

网络开发是指利用网络技术和工具构建、管理和维护网络应用程序或服务的过程。这涵盖了从设计和开发到部署和维护的全过程。网络开发可以包括网站开发、Web 应用程序开发、移动应用程序后端开发等方面。

B__B_B的博客 676

【S32K】S32K144入门笔记(3) SPI(lpspi组件)

0. 引言 与第二篇can对应,第三篇本来想写lin的,毕竟都是车身上常用的总线。但是lin比较麻烦,所以先拖后一下,先把SPI记录一下。 SPI在我们的系统架构中是S32K和ADAS之间做数据传输用的,毕竟速率够高,数据量能传的比较大。 1. 准备 1.1 SPI基础知识 1.2 开发环境 1.2.1 软件开发环境 1.2.2 硬件环境 SPI 2. Demo ...

YoYo的桃子树 2万+

State of GPT (ChatGPT 原理及现状介绍)

要用 RLHF 的一个简单的原因就是 RLHF 模型效果更好,下面的图来源于 InstructGPT 论文,PPO (RLHF 算法) 后的模型生成的答案更被人类喜欢。karpathy 认为 RLHF 有用的原因是判别比生成更容易,让标注员去写一些 SFT 的 QA 数据对是比较难的,如果有一个 SFT 模型生成一些数据让标注员判断哪个更好就简单很多。,GPT4 最强,前三个都是 RLHF 模型,其他模型都是 SFT 模型。伯克利做的模型评测榜单。

kebijuelun的博客 3581

自己动手开发网络服务器(一)

原文链接:http://ruslanspivak.com/lsbaws-part1/译文链接:http://codingpy.com/article/build-a-simple-web-server-part-one/有一天,一位女士散步时经过一个工地,看见有三个工人在干活。她问第一个人,“你在做什么?”第一个人有点不高兴,吼道“难道你看不出来我在砌砖吗?”女士对这个答案并不满意,接着问第二个人...

追求卓越 1万+

Syzkaller实战教程2:运行环境配置+实例运行

本文详细介绍了在linux系统上搭建Syzkaller内核模糊测试环境的完整流程。 1.环境配置:通过VMware创建Ubuntu20.04虚拟机A,配置QEMU/KVM虚拟化环境,安装Go语言工具链和Syzkaller; 2.内核编译:下载Linux内核源码并配置KCOV等调试选项,编译生成带覆盖率支持的bzImage内核镜像; 3.测试环境构建:使用debootstrap创建Debian虚拟机镜像,通过QEMU启动嵌套虚拟机B; 实例测试: 4.演示两种测试场景 - 提供完整上手教程

cuguanren的博客 1378

自己动手开发一个 Web 服务器(三)

在第二部分中,你开发了一个能够处理HTTPGET请求的简易WSGI服务器。在上一篇的最后,我问了你一个问题:“怎样让服务器一次处理多个请求?”读完本文,你就能够完美地回答这个问题。接下来,请你做好准备,因为本文的内容非常多,节奏也很快。文中的所有代码都可以在Github仓库下载。 首先,我们简单回忆一下简易网络服务器是如何实现的,服务器要处理客户端的请求需要哪些条件。你在前面两部分文章中开发

小桥流水的专栏 1931

PaddleOCR 与 PaddleX 调试

本文介绍了PaddleOCR与PaddleX的安装调试过程及应用对比。首先详细说明了环境准备步骤,包括安装ccache、设置环境变量及创建conda虚拟环境,提供了精简安装和源码安装两种方式。接着展示了使用PaddleOCR进行发票和手写汉字识别的测试结果,指出部分手写识别存在误差。随后对比了两者的差异:PaddleOCR专注于OCR算法优化,PaddleX则提供全流程工具链和标准化部署方案。最后演示了如何通过PaddleX部署OCR服务,包括API启动方法和客户端调用示例,为开发者提供了两种不同场景下的O

weixin_42176639的博客 1452

clock-gating整理

文章目录clock gating 理解1、latch双稳态器件常见锁存器结构SR锁存器D锁存器2、clock gating(clock low-active) latch + AND gating 电路(clock high-active)latch + OR gating 电路 clock gating 理解 1、latch 参考:https://www.cnblogs.com/IClearner/p/6443539.html 双稳态器件 稳定状态为0或1两种 举例:交叉耦合反相器 假设初始Q为1,则可

d_b_的博客 1万+

自己动手开发网络服务器

自己动手开发网络服务器,开发一个专属你的web服务器吧!

大布小凡的博客 554

基于STM32设计的电能质量控制系统_353

本项目基于STM32F103RCT6微控制器设计了一套电能质量控制系统,实现了对火焰、烟雾、环境温湿度、电压、电流及功率等多项参数的实时监测与报警。系统通过MQ2烟雾传感器、火焰传感器、SHT30温湿度传感器及电力参数采集模块采集数据,采用高电平触发有源蜂鸣器进行异常报警。采集的数据通过ESP8266无线模块以AP+TCP模式上传至基于Qt开发的手机APP和电脑上位机,实现远程实时监控和历史数据管理。系统配备1.44寸LCD显示屏,实现本地数据显示。软件采用Keil5开发,采用寄存器编程方式,提高系统响应速

255

从零开始搭建一个完整的web全栈开发环境并实现服务器部署(pycharm +Ubuntu+ django+uwsgi+nginx + neo4j/MySQL)

写在前面: 这基本是我第一次着手去搭建一套开发环境,从软件到依赖包到服务器部署,代码同步调试,从零看着一大堆资料到搭建出一个基本的开发环境并成功运行,我觉得有必要把其中的过程和对我有帮助的资料重新整理 linux操作:由于服务器系统大多在linux系统运行,所以熟练掌握linux的各种基本命令是非常重要的,但我觉得,单纯去学命令容易没有条理,可以跟着教程一步步做着去学,也能掌握每一步命令的用途 ...

u014581594的博客 2515

SAP PI/PO 传输治理,从 ESR 到 Integration Directory 的交付边界

SAP PI/PO项目中最容易被低估的是接口传输管理,而不仅是接口开发本身。传输涉及三层对象:ESR设计对象、Integration Directory配置对象和应用系统开发对象,三者必须协同传输。常见误区包括: 错误认为导出导入文件即完成传输 忽视传输顺序(应先传ESR再传Directory) 忽略应用系统对象的同步传输 过度依赖文件传输而缺乏治理 解决方案包括: 建立完整的传输清单 遵循先ESR后Directory的顺序 结合CMS进行轨道化管理 文件传输仅用于临时场景 严格区分环境相关配置 最终应将P

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 95

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

android 服务器 语言,Android后端服务器的搭建-Go语言中文社区

一直做Android前端,今天突然心血来潮想搭建一个后台玩玩。平时都是需要什么样的接口直接出个接口文档扔给后台的兄弟,自己从来不操心他们内部的实现问题。今天怀着好奇的心理去搭建了一个JAVA编译环境下的后台服务器。听说用PHP搭建服务器的居多,但是我们做大Android的最熟悉的还是Java了,所以下面我就开始搭建这个服务器。很简单。。。首先我下载了一个myelipse应为我们开发android的...

weixin_28718641的博客 254

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

ubuntu下源码安装apache2和php7

安装apache2 1.下载apache2: 点我转到下载地址 2.安装依赖sudo apt install libapr1-dev libaprutil1-dev sudo apt install libpcre3-dev zlib1g-dev3.安装./configure --prefix=/usr/local/apache2 --enable-rewrite --enable-so --e

Destinylan的博客 3254

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Sencha Touch---Getting Started with Sencha Touch 2

Getting Started with Sencha Touch 2 First, you'll need to download the freeSencha Touch 2 SDKandSDK Toolsfrom the Sencha website. You'll also need: A web server running locally on your co...

anguwei7911的博客 147

Modern Web Guidance 实战:用 sibling-index() 与 sibling-count() 实现动态兄弟元素样式

本文以仓库中的动态兄弟元素样式验收规范为主线,逐条拆解 `sibling-index()` / `sibling-count()` 在色谱、扇形与圆形布局中的用法,并给出 `CSS.supports()` 驱动的 JavaScript 回退方案与 `@supports` 覆盖结构。读完后你可以独立写出一个"元素增删后布局自动重算"的样式系统,并让配套的 Playwright grader 全部通过

gitblog_00087的博客 474

从零开始开发一个全栈Web应用实录

虽说学习了大半年前端,但是对前端的理解仍然停留在对HTML,CSS,JS,JQuery的概念理解上,并且没有接触过相关的后端开发,所以说,这个项目也可称为从零开始,是新手向的文章,不要害怕有门槛哈。项目耗时15天时间,100小时的工作量,13370行代码,内容是本校的学生选课系统。地址如下:http://115.159.6.187/ (偷懒没做手机端优化,推荐电脑访问嘿嘿) 前言做这个项目的原因呢

晨阳再升的博客 1万+

Eclipse的Web开发环境搭建——从零开始入门介绍

原文地址:http://www.datalearner.com/blog/1051504188229579使用Eclipse进行Web系统开发是一种非常流行的方式。本文将讲述如何从零开始搭建Eclipse的Web开发环境。 一JDK安装 二Tomcat安装 三Eclipse安装 四服务器环境设置 五界面字体设置 六代码缩进设置 七代码自动提示设置

DataLearnerAI 2万+

从零开始构建一个高性能的Web服务器

1.背景介绍 在现代互联网时代,Web服务器是构建在互联网基础设施之上的核心组件。它们负责处理来自客户端浏览器的请求,并将相应的资源(如HTML、CSS、JavaScript文件、图片等)返回给客户端。高性能的Web服务器是实现快速、可靠的网络服务的关键。 在本文中,我们将从零开始构建一个高性能的Web服务器,探讨其核心概念、算法原理、实现细节以及未来发展趋势。我们将涉及到以下主题: 背景...

AI天才研究院 1261

【Go Web 篇】从零开始:构建最简单的 Go 语言 Web 服务器

通过本篇博客,我们从头开始构建了一个最简单的 Go 语言 Web 服务器。我们了解了为什么选择 Go 语言来构建 Web 服务器,并通过实际的代码示例展示了如何创建一个基本的服务器并在浏览器中查看结果。尽管这只是一个简单的示例,但它奠定了你进一步探索 Go 语言 Web 开发的基础。从这里开始,你可以逐步深入学习更多关于路由、中间件、模板引擎、数据库交互等方面的知识,构建更加复杂和功能丰富的 Web 应用程序。无论。

繁依Fanyi的博客 6807

从零开始搭建树莓派web服务器

从零开始搭建树莓派web服务器 1.安装树莓派系统 ①进入https://www.raspberrypi.com/software下载系统镜像,下载完后会得到压缩包,它解压出来的文件后缀名是.img的就是系统镜像文件(解压的路径不能含中文) ②下载系统镜像写入工具:Win32DiskImager 下载内存卡格式化软件:SDFormatte 下载链接:https://wwe.lanzouj.com/iiyPHzaqc6j 格式化内存卡后写入.img文件,在盘里创建一个SSH文件,插卡运行树莓派 2.设置固定i

m0_47468934的博客 3681
上一篇: Vim与Python真乃天作之和
下一篇: 原来我一直安装 Python 库的姿势都不对呀!
codingpy
博客等级 码龄11年 1873粉丝 104原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值