在Python 3中每x秒发出一次API请求

时间:2017-05-23 15:17:16

标签: python-3.x

我正在尝试使用Python 3在服务器上进行压力测试。我们的想法是每隔1秒向API服务器发送一次HTTP请求,持续30分钟。我尝试使用requestsapscheduler来执行此操作,但我一直在

  

执行作业" send_request(触发:间隔[0:00:01],下次运行于:美国东部时间23:05:05:46)"   已跳过:达到最大运行实例数(1)

我该如何使这项工作?以下是我目前的代码:

import requests, json, time, ipdb
from apscheduler.schedulers.blocking import BlockingScheduler as scheduler

def send_request():
    url = 'http://api/url/'

    # Username and password
    credentials = { 'username': 'username', 'password': 'password'}

    # Header
    headers = { 'Content-Type': 'application/json', 'Client-Id': 'some string'}

    # Defining payloads
    payload = dict()

    payload['item1']    = 1234
    payload['item2'] = 'some string'
    data_array = [{"id": "id1", "data": "some value"}]
    payload['json_data_array'] = [{ "time": int(time.time()), "data": data_array]

    # Posting data
    try:
        request = requests.post(url, headers = headers, data =  json.dumps(payload))
    except (requests.Timeout, requests.ConnectionError, requests.HTTPError) as err:
        print("Error while trying to POST pid data")
        print(err)
    finally:
        request.close()

    print(request.content)

    return request.content

if __name__ == '__main__':
    sched = scheduler()
    print(time.time())
    sched.add_job(send_request, 'interval', seconds=1)
    sched.start()
    print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))

    try:
        # This is here to simulate application activity (which keeps the main thread alive).
        while true:
            pass
    except (KeyboardInterrupt, SystemExit):
        # Not strictly necessary if daemonic mode is enabled but should be done if possible
        scheduler.shutdown()

我尝试搜索堆栈溢出但是其他问题都没有达到我想要的目标,或者我可能错过了一些东西。如果是这样的话,我希望有人能指出我正确的主题。非常感谢你!

2 个答案:

答案 0 :(得分:0)

我以前从未在python中使用过调度程序,但是other stackOverflow question似乎处理了这个问题。

  

这意味着该任务花费的时间超过一秒,默认情况下,对于给定的工作,只允许一次并发执行......-AlexGrönholm

在您的情况下,我想使用线程可以满足您的需求。 如果你创建了一个在python中继承线程的类,比如:

class Requester(threading.Thread):
  def __init__(self, url, credentials, payload):
    threading.Thread._init__(self)
    self.url = url
    self.credentials = credentials
    self.payload = payload        
  def run(self):
    # do the post request here
    # you may want to write output (errors and content) to a file
    # rather then just printing it out sometimes when using threads 
    # it gets really messing if you just print everything out

然后就像你稍微改变一样处理。

if __name__ == '__main__':
  url = 'http://api/url/'
# Username and password
  credentials = { 'username': 'username', 'password': 'password'}
# Defining payloads
  payload = dict()
  payload['item1']    = 1234
  payload['item2'] = 'some string'
  data_array = [{"id": "id1", "data": "some value"}]
  payload['json_data_array'] = [{ "time": int(time.time()), "data": data_array]
  counter = 0
  while counter < 1800:
    req = Requester(url, credentials, payload)
    req.start()
    counter++
    time.sleep(1)

当然,如果您愿意,可以完成其余部分,以便您可以使KeyboardInterrupt实际完成脚本。

这当然是绕过调度程序的一种方法,如果这就是问题所在。

答案 1 :(得分:0)

我认为我的错误是由我标记的副本以及@jeff

的答案所描述的

编辑:显然不是..所以我在这里描述如何解决最大实例问题:

最大实例问题

当您向调度程序添加作业时,您可以为作业的最大允许并发实例数设置一个参数。你可以 在这里阅读: BaseScheduler.add_job()

因此,解决问题只是将其设置为更高的问题:

sch.add_job(myfn, 'interval', seconds=1, max_instances=10)

但是,您想要多少个并发请求?如果他们需要超过一秒钟的时间来回复,并且您每秒请求一次,那么如果您让它运行得足够长,那么最终会最终错误...

的调度程序

有几个可用的调度程序选项,这里有两个:

BackgroundScheduler

您正在导入阻止调度程序 - 阻止调度程序在启动时会阻塞。因此,在调度程序停止之后,其余代码才会执行​​。如果在启动调度程序后需要执行其他代码,我会使用这样的后台调度程序:

from apscheduler.schedulers.background import BackgroundScheduler as scheduler

def myfn():
    # Insert your requests code here
    print('Hello')

sch = scheduler()
sch.add_job(myfn, 'interval', seconds=5)
sch.start()

# This code will be executed after the sceduler has started
try:
    print('Scheduler started, ctrl-c to exit!')
    while 1:
        # Notice here that if you use "pass" you create an unthrottled loop
        # try uncommenting "pass" vs "input()" and watching your cpu usage.
        # Another alternative would be to use a short sleep: time.sleep(.1)

        #pass
        #input()
except KeyboardInterrupt:
    if sch.state:
        sch.shutdown()

BlockingScheduler

如果您在启动调度程序后不需要执行其他代码,则可以使用阻止调度程序,它更容易:

apscheduler.schedulers.blocking import BlockingScheduler as scheduler

def myfn():
    # Insert your requests code here
    print('Hello')

# Execute your code before starting the scheduler
print('Starting scheduler, ctrl-c to exit!')

sch = scheduler()
sch.add_job(myfn, 'interval', seconds=5)
sch.start()