以下代码部分中user_input = post_data.split('=')[1] 是什么?

What is user_input = post_data.split('=')[1] present in the following section of code?

提问人:TheFloof 提问时间:11/10/2023 最后编辑:marc_sTheFloof 更新时间:11/23/2023 访问量:69

问:

我正在编写一段 python 代码来处理来自 html 服务器的 POST 请求方法。下面的代码块是在我之前提出的问题的答案中提供给我的。我一直在一行一行地浏览它,以确保我理解这里的逻辑。

但我尤其在这条线上遇到了障碍。

user_input = post_data.split('=')[1]

因此,我将概述我认为逻辑正在做什么,然后提供实际代码,我希望有人可以在适当的地方纠正我,以确保我真正正确理解逻辑。并进一步解释为什么上面指示的代码行存在,我不明白为什么在这种情况下需要拆分方法。

难道post_data不能简单地按原样打印出来吗?或者这会因为某种原因导致问题吗?

我在这里的顶部部分提供上下文,因为它是程序的其余部分。

# Python 3 server example
from  http.server import BaseHTTPRequestHandler, HTTPServer 
import time #Why is time imported if it's not used? Hypothesis: the send response method on line 10 states among other things to send the current date. Thus time is needed to determine current date?

hostName = "localhost"
serverPort = 8080

class MyServer(BaseHTTPRequestHandler): 
    def do_GET(self): 
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        self.wfile.write(bytes("<html><head><title>https://pythonbasics.org</title></head>", "utf-8"))
        self.wfile.write(bytes("<p>Request: %s</p>" % self.path, "utf-8"))
        self.wfile.write(bytes("<body>", "utf-8"))
        self.wfile.write(bytes("<p>Hello world! This is a webpage!</p>", "utf-8"))
        self.wfile.write(bytes("<p> And hello to you! Please enter your name below!</p>", "utf-8"))
        self.wfile.write(bytes("""<form action="/" method="post">
                                   <label for="name">Please enter your name:</label><br>
                                   <input type="text" id="name" name="name"><br>
                                   <input type = "submit" value = "Click me!">
                                </form>  
                              """, "utf-8" )) 
        self.wfile.write(bytes())
        self.wfile.write(bytes("</body></html>", "utf-8"))

下面的部分是我想验证我的理解的代码部分。我认为这里在逻辑上发生的事情,并且代码中的注释中包含了一些其他问题。

def do_POST(self): 
        content_length = int(self.headers['Content-Length']) 
        #The content-string above is an html header responsible for declaring the length of the text being passed to the server via the POST method. 
        #However, Content-Length is never declared a value that I can tell, not here or in the rest of the program. So, does HTML then by default take the entire doccument provided by the POST method if Content-Lengtg is not assigned any value?
        # It is then coerced into an int and passed to the content_length variable. But what is the purpose of the ".headers" method?
       
        post_data = self.rfile.read(content_length).decode('utf-8') 
        #utf-8 is the unicode format for encoding/decoding the given text. .read is being passed the length of the message and thus is reading the entire message. The message is then passed to .rfile, I am not sure why this is, why is the standard .read method not sufficent?
        
        user_input = post_data.split('=')[1] 
        #I really have no idea why this the split method is needed at all. Could post_data not be used as it is?

        self.send_response(200) 
        #Sends the webpage the 200 response code indicating the server processed the request correctly.
        self.send_header('Content-type', 'text/html')
        #Declares that the data about to be sent is of the type text, and is written in HTMl
        self.end_headers()

        self.wfile.write(bytes("html>head>title>https://pythonbasics.org</title>/head>", "utf-8"))
        #I don't understand the use of the bytes class in these lines. I'm assuming that html needs information passed to it to be encoded into bytes for the transfer? This class does so?
        self.wfile.write(bytes("<body>", "utf-8"))
        self.wfile.write(bytes(f"<p>Hello {user_input}!</p>", "utf-8"))
        #At the beginning of this string after the bytes class ther is a single "f" present. Why is this? Is it something to do with html coding or python? Also am I right in thinking that {user_input} is the syntax in HTML for inserting a variable?
        self.wfile.write(bytes("</body></html>", "utf-8"))
html python-3.x 服务器 逻辑

评论

4赞 pho 11/10/2023
您是否检查了代码的内容,并查看了如果您不拆分并采用结果列表的第二个元素,稍后在代码中会发生什么?post_data'='
0赞 Barmar 11/10/2023
它设置为字符之后的部分。user_inputpost_data=
0赞 John Gordon 11/10/2023
你是在问那段代码是做什么的,还是在问作者为什么选择这样写?
0赞 TheFloof 11/10/2023
我问作者为什么选择包含该特定行,它在程序逻辑中的目的是什么。为什么需要它?

答:

0赞 gamez_code 11/10/2023 #1

原因是因为post_data变量包含“name=<the_text_input>”,那么如果你想要文本输入值;您必须拆分字符串并获得最后一部分。

0赞 Ralubrusto 11/10/2023 #2

作为软件开发人员工作时,您开发的众多东西之一就是尝试事物的能力。可能发生的最糟糕的事情是什么?错误,到处都是错误(如果你得到参考,请用巴斯光年的声音阅读)......

我们喜欢遇到错误和错误吗?好吧,通常不会......但我们也不总是难过。错误是通过清理代码、创建有用的日志、了解新的包功能等来学习的机会。

我的观点是:不要害怕测试。如果你面对的是别人的代码,并且你不确定某些东西做了什么,或者为什么它甚至在那里,不要害怕删除它并重新运行代码!

例如。。。您已经注意到该包已导入但未使用。您可以删除它,看看会发生什么!(剧透:效果很好。运行代码根本不需要该包)time

另一个有用的功能是搜索和阅读软件包文档。是的,它有时很无聊,但在大多数情况下,它会节省你的一天,甚至教你一两件新东西。

例如。。。你已经问过 Inside the Method 的使用。首先,您需要了解您的服务器基于名为 .更准确地说,您的类继承自 ,这意味着它们都具有相同的属性和方法。byteswritehttpBaseHTTPRequestHandlerBaseHTTPRequestHandler

(提示:如果你不理解继承的概念,也许你应该退后一步,在深入研究这个 Web 服务器这样的例子之前,先加强面向对象编程的概念。

从已经编码的类继承时,查看文档总是一个好主意。我会为您节省几次点击,并将链接直接放在这里

在那里,您可以找到有关属性的信息。据说wfile

wfile
包含用于将响应写回客户端的输出流。 写入 此流,以便实现与 HTTP 的成功互操作 客户。

在 3.6 版更改: 这是一个 io.BufferedIOBase 流。

文档实际上是将我们重定向到另一个文档,这很好。它经常发生。我们现在需要知道什么是“io.BufferedIOBase 流“是。或者,更具体地说,我们需要知道它的方法是什么。write

文档非常简单,在第一句话中给了我们答案:

writeb, /)
写入给定的类字节对象 b,并返回 写入的字节数(始终等于 b 的长度(以字节为单位), 因为如果写入失败,将引发 OSError)。[...]

谜题已经解开。该方法需要一个“类字节”对象作为输入,因此这就是我们在调用 .writebytesself.wfile.write

这两项技能(测试和阅读文档)是您开发的核心工具,可以更好地了解软件开发世界中的工作方式。我觉得在回答你的具体问题之前,先给你这个背景是很重要的。但现在让我们走吧

为什么需要?split

我将在这里花一些时间给大家介绍一些其他主题。我不是专家,但希望你会觉得这很有趣。

使用 HTTP 表单时,了解用户传递的信息如何发送到服务器非常有用。为此,您可以运行服务器代码,通过任何浏览器访问其页面链接,然后打开“devtools”(在此链接上查看如何操作)。最后,打开“网络”选项卡

一开始你会看到它是空的,但随后只需测试你的代码:输入你的名字,然后单击按钮。现在,可能已经出现了一些请求。

查找 POST 请求,因为它是按钮单击事件调用的请求。我们怎么知道呢?在您的代码中,标签具有以下选项,它表示服务器在单击该按钮时运行 POST 类型的方法。<form><form action="/" method="post">

选择 POST 请求后,查找其标头。它有很多,但现在只有一个是有用的:“Content-Type”。它说明了如何在请求中写入来自用户的输入数据。请参阅下面的打印屏幕

A piece of the POST request header

声明我们将写成名称-值对的信息,如等(在 SO 上有一些关于这个问题的答案,例如这个application/x-www-form-urlencodedname1=value1&name2=value2&name3=value3)

这开始敲响警钟,不是吗?但是,让我们再潜入一些。您可以在“有效负载”选项卡上查看发送到服务器的实际信息。我也为你打印了它

The POST request payload

你可以猜到我写了一首单曲并点击了按钮。但是看,这是浏览器发送的信息。属性的名称为“name”,因为表单标记内的选项。如果您将其更改为我们在浏览器中看到的内容。Xlabel<label for="banana">banana=X

这就是浏览器将信息发送到服务器的方式。从服务器端,您需要以某种方式阅读它。这是通过该方法实现的。rfile.read

现在您知道了文档的路径,您将了解此方法需要一个整数来表示要读取的字节数。令人高兴的是,这个字节数在请求标头的键“Content-Length”下发送。

您可以在第一次打印时检查,在我的情况下,“Content-Length”是 6:属性 () 的名称长度为 4 个字节;符号长度为 1 字节;我的答案 () 也是 1 个字节长。这就是为什么 Content-Length 是 6。name=X

到现在为止,您可能已经弄清楚了一切:

  • 您需要该变量来获取 POST 有效负载的大小(以字节数为单位)content_length
  • 读取有效负载时,您会得到类似“名称/值”对的信息,该对由分隔=
  • 由于您只想打印,因此您只需要值,因此您需要有效载荷,"Hello {user_answer}"splitname=user_answer

这是对代码“为什么”这样编写的相当长的解释。我经常喜欢阅读文档的旅程,但我知道这可能很无聊。

理解“为什么”的另一种方法是更改代码以打印整个代码而不进行拆分。然后你会看到打印出来的,你可能会自己弄清楚一切。post_dataname=answer

我希望你已经学到了一两件事。如果您愿意,请随时询问更多。祝你编码愉快 (: