【问题标题】:Can I get CherryPy to find its own available port?我可以让 CherryPy 找到它自己的可用端口吗?
【发布时间】:2013-12-12 01:39:56
【问题描述】:

出于测试目的,我在同一台机器上运行了许多 Web 服务器。我不想处理服务器端口冲突,而是让服务器简单地向操作系统询问可用端口,然后告诉我他们得到了什么。

我可以通过登录到控制台或写入指定的临时文件(尚不确定)将端口传回给调用者,但知道端口号是棘手的部分。

目前,正在启动基于 WSGI 的服务器:

  cherrypy.quickstart(dev_server, config=_GetConfig(options))

配置将包含以下内容:

{ 'global':
                  { <snip>
                    'server.socket_host': '0.0.0.0',
                    'server.socket_port': int(options.port)
                  },
   <snip>
}

有没有办法用 CherryPy 做到这一点?

我假设我可以将端口设置为“0”以使其自动选择,但这并没有给我提供报告的方法。

【问题讨论】:

  • 您希望他们如何告诉您他们得到了什么?打印到控制台?登录到系统日志?将其写入运行文件?连接到某个主服务器并通过某个 API 发送它?
  • 是否有那么多 Web 服务器在争夺一个端口?随机尝试端口的循环将在几轮后找到一个。但是,在您对@abarnert 评论做出答复之前,请不要考虑那个循环。
  • 另外,请告诉我们您是如何启动服务器以及如何配置它们的,因为 CherryPy 具有很大的灵活性。
  • 现在,每个测试实例都是它自己的 Python 进程,独立于其他实例启动。 CherryPy 实际上是通过以下方式启动的:cherrypy.quickstart(dev_server, config=_GetConfig(options))

标签: python cherrypy


【解决方案1】:

基本思路是:

  • 绑定到端口 0。
  • 询问套接字您最终使用了哪个端口。
  • 以某种方式报告该端口。

第一部分从根本上取决于您如何构建、启动和配置服务器。 CherryPy 非常灵活,具体取决于您使用它的方式。

第二部分要求您使用某种机制来编写启动服务器的顶级代码,并且不是在没有任何代码的情况下自动启动它们的机制之一.这是因为,在启动服务器之前,您需要手动bind 服务器来获取它的套接字。一旦您创建并绑定了套接字,getsockname 将为您提供最终绑定到的地址和端口。

第三部分显然可以随心所欲地简单或困难。


这是一个简单的示例,您甚至可以从交互式解释器中完成:

def app(env, start):
    start('200 OK', [('Content-type', 'text/plain')])
    return ['Hello, world!']
server = cherrypy.wsgiserver.CherryPyWSGIServer(('0.0.0.0', 0), app,
                                                server_name='localhost')
server.bind(socket.AF_INET, socket.SOCK_STREAM)
addr, port = server.socket.getsockname()
print(port)
server.start()

您可能还想看看cherrypy.process.servers 及其ServerAdapter,它可以让您从一个地方管理多个服务器,而不是拥有一堆必须手动协调的独立服务器。

【讨论】:

  • 有时我觉得我们只是“太容易”“放弃”解决问题。不过答案很好:)
  • @JamesMills:如果他碰巧使用的是平面CherryPyWSGIServer,并且所有配置都硬编码在源代码中,那么这只会给出解决方案,我真的怀疑他正在使用。我希望他能够弄清楚如何适应他实际正在所做的事情,和/或在文档中找到相关信息,和/或至少提出一个更好的问题就足够了……
  • sigh :) 我确实承认,但你的回答是/比我的措辞和组织更好:)
  • 您的回答正是我所需要的。这些脚本是我继承的,但没有深入研究。特别是,我没有意识到 CherryPy 如此灵活,或者可以以多种不同的方式使用。
【解决方案2】:

如果您使用的是 CherryPy 的内置服务器,您可以使用 cherrypy.server.bound_addr 检查它实际监听的端口。

文档说:

属性 bound_addr

绑定地址,或者如果它是一个临时端口并且套接字已经 bound,返回实际绑定的端口。

一个使用这个的例子:

def start():
    cherrypy.config.update({
        'server.socket_port': 0,
    })
    cherrypy.tree.mount(MyApp(), '', {})

    cherrypy.engine.signals.subscribe()
    cherrypy.engine.start()
    _host, port = cherrypy.server.bound_addr

    # Do something with the port here
    ...

    cherrypy.engine.block()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    • 2014-01-19
    • 2020-02-26
    • 2017-01-09
    相关资源
    最近更新 更多