【问题标题】:Using 'while True' while doing http request in Python 2.7在 Python 2.7 中执行 http 请求时使用“while True”
【发布时间】:2014-03-28 23:01:21
【问题描述】:

是否有更 Pythonic (2.7) 的方法来检查服务器是否有不包括使用 while True 的良好 status_code (200)?我的代码 sn-p 如下 - 它被多次调用:

    import time
    import json
    from datetime import datetime
    import requests

    while True:
        response = requests.get('http://example.com')
        if response.status_code != 200:
            print 'sleeping:',str(datetime.now()),response.status_code
            print 'sleeping:',str(datetime.now()),response.headers
            time.sleep(5.0)
        else: break
    if "x-mashery-error-code" in response.headers:
        return None
    return response.json()

编辑:我在标题错误中包含了“if”循环。

【问题讨论】:

  • 这个代码是用来检查服务器健康状况的工具吗?
  • @praveen 不,我需要 response.json() 中的数据。但服务器有限制,也可能发送非 200 码。
  • 使用while 1: 如果while True: 是问题,那是显而易见的解决方案。但真正的问题是什么?你能写更多吗?
  • 'while True' 不是问题,但我想问这些天在 python 中是否有更好的做法
  • 还可以看看这个:stackoverflow.com/questions/14236426/… 有一个重试计数器可能会在您受到限制的情况下妨碍您

标签: python python-2.7 python-requests


【解决方案1】:

我通过将装饰器应用于诸如重试之类的事情来使用面向方面的编程。如果我获取我想要的值的函数如下所示:

def getValue():
  return requests.get('http://example.com')

然后我装饰这个函数以应用重试机制而不干扰原始(幼稚)代码:

def retryUntilCondition(condition):
  def decorate(function):
    def f(*args, **kwargs):
      while True:
        result = function(*args, **kwargs)
        if condition(result):
          return result
        time.sleep(5.0)
    return f
  return decorate

def responseIs200(response):
  return response.status_code == 200

上面是准备(一个实用程序库的一部分),下面是用法:

@retryUntilCondition(responseIs200)
def getValue():
  return requests.get('http://example.com')

这样while 循环就完全隐藏在应用程序代码中,并且不会使阅读变得复杂。重试的方面是通过添加一个简单的装饰器来添加的,甚至可以在其他情况下重用。

如果稍后您决定只想重试特定次数、有不同的延迟等,所有这些都可以单独在 retry 装饰器中实现。

【讨论】:

  • 这是一个非常优雅的解决方案,但我需要其他人以后可以修改的东西。
【解决方案2】:

我想要这个解决方案:

response = requests.get('http://example.com')
while response.status_code != 200:
    print 'sleeping:',str(datetime.now()),response.status_code
    print 'sleeping:',str(datetime.now()),response.headers
    time.sleep(5.0)
    response = requests.get('http://example.com')

因为:

>>> import this
...
Explicit is better than implicit.
Simple is better than complex.
...
Flat is better than nested.
...
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
...
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
...

因为我阅读它并立即理解它。对于事件挂钩,情况并非如此。他们是否打开一个线程来并行检索字节?他们什么时候叫?我需要自己检索数据吗?

【讨论】:

  • 我喜欢它,但这不是对服务器的请求数量增加了一倍吗?
  • 此解决方案的主要缺点是代码加倍。如果 URL 稍后发生更改,您很可能忘记在两个位置进行调整(考虑它们之间的距离较远)。
  • @philshem 它与您的代码完全一样。 @Alfe 我想您可以将其重构为变量。或者您将整个请求重构为一个函数。你可以做到的。
  • @user 是的,我明白了。
  • 我接受(并使用)了这个解决方案,因为它允许非核心编码人员在未来进行修改。同样出于我的目的,添加一个在 N 次尝试后退出程序的计数器很容易。
【解决方案3】:

你可以使用Event Hooks

requests.get('http://example.com', hooks=dict(response=check_status))
def check_status(response):
    if response.status_code != 200:
        print 'not yet'

【讨论】:

  • 非常好。 sleep 语句也可以进入 'if' 循环?
  • 好吧,我不认为你真的需要睡觉......你以这种方式异步发送请求。如果您想等到请求完成,您可以简单地在下一个 url 达到状态 200 时调用另一种方法。您应该尝试不同的想法;)
猜你喜欢
  • 2016-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多