• Python学习笔记7:文件


    Python学习笔记7:文件

    对于程序的数据存储,最简单的方式无非是使用文件。其实数据库也是一种特殊的文件系统,它通过一些数据结构,利用文件系统来架构了一个高可靠性高性能的数据存储与读取服务。

    文件的基本使用

    无需引入其它模块,Python本身就提供内置函数open()以支持对文件的基本操作。

    fopen = open(file='main.log', mode='r')
    for line in fopen:
        print(line)
    fopen.close()
    

    输出

    2021-03-05 17:16:34,829 - set.py[line:4] - this is error message1

    2021-03-05 17:16:34,831 - set.py[line:5] - this is error message2

    open指定了两个参数,file说明了要打开的文件,mode则是打开方式,主要分为以下几种:

    • r:只读,如果文件不存在,报错。
    • w:写入,会覆盖原有内容。
    • a:追加,在原有内容尾部写入新内容。
    • x:检测文件是否存在,如果不存在,创建一个新文件。
    • 需要说明的是,除了r模式,其它三种如果文件不存在,都会新建一个文件。
    • 除了mod='r'这种指定单个模式,还可以使用mod='r+',这表示同时具有读写模式,还有mod='r+b'表示同时读写二进制文件。

    此外,在获取到打开的文件句柄fopen后,我们可以很容易地用for/in的方式逐行获取文件内容,这是Python对文件句柄采取了类似遍历器的设计,而且非常智能地在文件结束后结束循环,对比同类代码在PHP或Java中的写法,无疑非常直观和方便。

    但Python所做的优化不仅于此,有过其它语言文件操作经历的开发者应该都清楚,用写入模式打开一个文件后会加文件锁,这是独占式地使用文件,此时其它程序是无法使用这个文件的。所以在写入完毕后你必须及时关闭文件,否则会产生一系列问题。但频繁的文件操作很可能就让开发者忘记在某处关闭文件。对此,Python有个很不错的设计:

    with open(file='main.log', mode='r') as fopen:
        for line in fopen:
            print(line, end='')
    

    输出

    2021-03-05 17:16:34,829 - set.py[line:4] - this is error message1
    2021-03-05 17:16:34,831 - set.py[line:5] - this is error message2

    可以看到我们使用with/as的方式进行文件读取,而且省略了文件关闭的操作。实际上这种写法在Python中称作上下文管理,Python会在with后的程序块运行完毕后自动进行相应的扫尾工作,在这个文件读取的场景,自然是自动调用文件关闭操作。是不是相当不错?

    此外,在print()中我们指定了一个end参数,这是为了避免在读取文件行输出的时候额外加入换行符,毕竟原始文件每行后是有换行符的,这里可以通过end参数移除或改变print的结束符号。

    现在我们已经掌握了基本的文件操作,我们来改进一下上一篇笔记Python学习笔记6:Web应用中的web应用,让这个web应用具有记录和展示http请求信息的功能。

    改进web应用

    本文改进的web应用最终代码已上传到百度盘:

    链接:https://pan.baidu.com/s/17k1OKuKARS9ayWTKRaldOg
    提取码:v8hl
    复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V1的分享

    我们需要先审视一下我们想记录哪些http请求信息:

    @web.route("/results", methods=["POST"])
    def results() -> 'html':
        """展示一个结果页面"""
        return str(dir(request))
        string = request.form['phrase']
        search = request.form['letters']
        results = set(string).intersection(set(search))
        return render_template("results.html", the_phrase=string, the_letters=search, the_results=str(results))
    

    我们在跳转到results页面时候拦截一下request,并输在页面输出,看一下request包含哪些信息:

    经过分析我们确定以下三个作为请求信息记录:

        userAgent=request.user_agent
        remoteAddr=request.remote_addr
        formData=request.form
    

    我们现在加入日志写入部分:

    from flask import Flask, render_template, request
    web = Flask(__name__)
    
    
    def writeLog(logInfo: list) -> None:
        with open(file="http.log", mode="a") as fopen:
            logStr = "|".join(logInfo)
            print(logStr, file=fopen)
    
    
    @web.route('/')
    def index() -> 'html':
        """展示一个字符串匹配的查询页面"""
        return render_template("entry.html", the_title="字符串匹配")
    
    
    @web.route("/results", methods=["POST"])
    def results() -> 'html':
        """展示一个结果页面"""
        userAgent = request.user_agent
        remoteAddr = request.remote_addr
        formData = request.form
        string = request.form['phrase']
        search = request.form['letters']
        results = set(string).intersection(set(search))
        logInfo = [str(userAgent), str(remoteAddr), str(formData), str(results)]
        writeLog(logInfo)
        return render_template("results.html", the_phrase=string, the_letters=search, the_results=str(results))
    
    
    web.run(debug=True)
    

    现在再次通过浏览器测试,就能看到项目目录下生成了日志文件:

    Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36|127.0.0.1|ImmutableMultiDict([('phrase', 'sjlfjdskljlkiwerwr'), ('letters', 'aeiou')])|{'i', 'e'}
    Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36|127.0.0.1|ImmutableMultiDict([('phrase', 'sjlfjdskljlkiwerwr'), ('letters', 'sdfdsf')])|{'d', 'f', 's'}
    

    现在日志有了,还需要加一个web页面用于展示,我们新建一个显示日志的模板文件log.html

    {% extends 'base.html' %}
    
    {% block body %}
    
    <h2>{{ the_title }}</h2>
    
    
    <p>服务器日志http请求日志:</p>
    <table>
        <tr>
            <th>浏览器标签</th>
            <th>客户端ip</th>
            <th>表单内容</th>
            <th>返回信息</th>
        </tr>
            <td>firefox</td>
            <td>127.0.0.1</td>
            <td>xxxxxxx</td>
            <td>xxxxxxx</td>
    </table>
    
    {% endblock %}
    

    index.py中加入路径重写并渲染模板:

    @web.route('/log')
    def showLog() -> 'html':
        """展示日志页面"""
        return render_template("log.html", the_title="服务器日志")
    

    访问页面http://127.0.0.1:5000/log

    现在我们修index.py,准备给模板的数据:

    def getLog() -> list:
        lines = []
        with open(file="http.log", mode="r") as fopen:
            for line in fopen:
                lines.append(line.split("|"))
        return lines
    
    @web.route('/log')
    def showLog() -> 'html':
        """展示日志页面"""
        logList = getLog()
        return render_template("log.html", the_title="服务器日志", log_list=logList)
    

    修改模板文件,以接收数据,这里可以用模板的循环语句来实现:

    {% extends 'base.html' %}
    
    {% block body %}
    
    <h2>{{ the_title }}</h2>
    
    
    <p>服务器日志http请求日志:</p>
    <table>
        <tr>
            <th>浏览器标签</th>
            <th>客户端ip</th>
            <th>表单内容</th>
            <th>返回信息</th>
        </tr>
        {% for log_line in  log_list %}
        <tr>
            {% for log_item in log_line %}
            <td>{{ log_item }}</td>
            {% endfor %}
        </tr>
        {% endfor %}
    </table>
    
    {% endblock %}
    

    用浏览器访问日志页面:

    OK!

    本篇文章首发自魔芋红茶的博客https://www.cnblogs.com/Moon-Face/ 请尊重其他人的劳动成功,转载请注明。
  • 相关阅读:
    最近一月研报推荐次数最多的最热股票
    【2019年07月22日】A股最便宜的股票
    【07月19日】指数估值排名
    北上资金近1周流入排行榜
    主要股东近3年净买入排名
    【07月16日】A股滚动市净率PB历史新低排名
    【07月15日】A股滚动市盈率PE最低排名
    最近3年股息率最高排名
    主要股东近3年净买入排名
    【07月09日】预分红股息率最高排名
  • 原文地址:https://www.cnblogs.com/Moon-Face/p/14532181.html
Copyright © 2020-2023  润新知