Python文档包括an example of creating an HTTP server:
def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
server_address = ('', 8000)
httpd = server_class(server_address, handler_class)
httpd.serve_forever()
RequestHandler
类提供给Server
,然后由Server
自动示例化处理程序。
假设我想在创建请求处理程序时将自定义参数传递给它。我怎么能和应该这样做?
更具体地说,我想从命令行传入参数,而必须在请求处理程序类中访问sys.argv
似乎不必要地笨拙。
通过覆盖Server
类的一部分似乎可以做到这一点,但我觉得我忽略了一个更简单、更好的解决方案。
9条答案
按热度按时间zbq4xfa01#
我在代码中使用“部分应用”解决了这个问题。
示例使用Python 3编写,但部分应用程序在Python 2中的工作方式相同:
这与类工厂非常相似,但在我看来,它有几个微妙的优势:
partial
对象比工厂函数定义和返回的嵌套类更容易内省它们内部的内容。partial
对象可以用pickle
序列化,而工厂函数中的嵌套类定义则不能(至少在不特意在类上编写__reduce__
方法的情况下不能)。partial
将参数显式地“预附加”到其他Python和正常的类定义中,比嵌套的类定义更容易阅读,理解和验证正确性(认知负荷更少), Package 函数的参数隐藏在其中的某个地方。唯一真实的的缺点是,许多人不熟悉
partial
-但根据我的经验,无论如何,* 每个人 * 最好 * 熟悉partial
,因为partial
在许多地方都有一种方式作为一个简单且可组合的解决方案出现,有时出乎意料,比如这里。gojuced72#
使用类工厂:
6ljaweal3#
在写这篇文章的时候,这里所有的答案基本上都坚持(非常尴尬的)意图,即
socketserver
模块的作者似乎认为传入的处理程序是一个类(即构造器)。实际上,处理程序唯一需要的是它是可调用的,因此我们可以通过使处理程序类的示例可调用并在调用时让它们运行超类的__init__
代码来解决socketserver
API。在Python 3中:这使得超类“constructor”调用不在
__init__
中,从而消除了在子类的构造函数完成之前分派请求(来自超类的构造函数)的可能性。注意,__init__
覆盖必须存在以转移执行,即使初始化不需要它;使用pass
的空实现将起作用。通过这种设计,奇怪的接口被隐藏起来,使用API看起来更自然:
lf3rwulv4#
我只想对托马斯·奥罗斯科的回答发表评论,但既然我不能…也许这会帮助其他也遇到这个问题的人。在Python3之前,Python有“旧式”类,
BaseHTTPRequestHandler
似乎就是其中之一。所以,工厂应该看起来像以避免像
TypeError: must be type, not classobj
这样的错误。vfh0ocws5#
为什么不直接子类化RequestHandler呢?
yquaqz186#
Ref子类化
HTTPServer
是另一种选择。服务器上的变量可以通过self.server.context
在请求处理程序方法中访问。它基本上是这样工作的:trnvg8h37#
如果你不需要示例属性,而只需要类属性,你可以使用这种方法:
或者你可以:
并在RequestHandler中使用以下命令检索:
b4qexyjb8#
使用lambda是一种非常简单的方法来创建一个新函数,该函数接受请求处理程序args并创建您的自定义类。
这里我想传递一个将在
do_POST()
中使用的变量,并设置SimpleHTTPRequestHandler
使用的目录,因此setup调用完整程序:
7nbnzgx99#
你可以使用
global
,就像这样。请谨慎使用,例如在您自己家中的隐私处。