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

Python 3.x 在Python3中每x秒发出一次API请求,python-3.x,Python 3.x,我正在尝试使用Python3在服务器上进行压力测试。其思想是每1秒向API服务器发送一个HTTP请求,持续30分钟。我尝试使用请求和apscheduler来执行此操作,但我不断收到 执行作业“发送请求(触发器:间隔[0:00:01],下次运行时间:2017-05-23 11:05:46 EDT)” 跳过:已达到最大运行实例数(1) 我怎样才能做到这一点?以下是我目前的代码: import requests, json, time, ipdb from apscheduler.schedulers

我正在尝试使用Python3在服务器上进行压力测试。其思想是每1秒向API服务器发送一个HTTP请求,持续30分钟。我尝试使用
请求
apscheduler
来执行此操作,但我不断收到

执行作业“发送请求(触发器:间隔[0:00:01],下次运行时间:2017-05-23 11:05:46 EDT)” 跳过:已达到最大运行实例数(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()

我试着在堆栈溢出上搜索,但到目前为止,没有一个问题符合我的要求,或者我遗漏了什么。如果是这样的话,我希望有人能给我指出正确的线索。多谢各位

我以前从未在python中使用过调度程序,不过这似乎可以解决这个问题

这意味着任务花费的时间超过1秒,默认情况下,给定作业只允许一次并发执行-亚历克斯·格伦霍姆

在您的情况下,我认为使用线程可以满足您的需要。 如果您创建了一个继承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)
如果uuuu name_uuuu=='\uuuuuuu main\uuuuuu':
url='1〕http://api/url/'
#用户名和密码
凭据={'username':'username','password':'password'}
#定义有效载荷
有效载荷=dict()
有效载荷['item1']=1234
有效负载['item2']='some string'
data_数组=[{“id”:“id1”,“data”:“some value”}]
有效负载['json_data_array']=[{“time”:int(time.time()),“data”:data_array]
计数器=0
当计数器小于1800时:
req=请求者(url、凭证、有效负载)
请求启动()
柜台++
时间。睡眠(1)
当然,不管你怎么想,你都可以完成剩下的部分,如果你想的话,你可以这样做,键盘中断就是真正完成脚本的部分


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

我认为我标记的副本以及@jeff的答案很好地描述了您的错误

编辑:显然不是..所以这里我将描述如何修复最大实例问题:

最大实例问题 将作业添加到计划程序时,可以为作业允许的最大并发实例数设置一个参数。您可以应该阅读以下内容:

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

sch.add_job(myfn, 'interval', seconds=1, max_instances=10)
但是,您需要多少并发请求?如果它们需要一秒钟以上的时间响应,而您每秒请求一个请求,那么如果您让它运行足够长的时间,您最终总会得到一个错误

调度者 有几个可用的计划程序选项,以下是两个:

背景调度器 您正在导入blocking scheduler(阻塞计划程序)-它在启动时会阻塞。因此,在计划程序停止后,才会执行其余代码。如果启动计划程序后需要执行其他代码,我将使用如下后台计划程序:

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()
阻塞调度器 如果启动调度程序后不需要执行其他代码,则可以使用阻塞调度程序,这更简单:

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()

@calico_uu的可能副本谢谢,我们很快就会查看它。@calico_u是的,问题是请求需要超过1秒。但是由于这是一个压力测试,如果请求已经存在,我不能跳过请求。我希望代码能够做的是,即使之前的请求没有完成/正在进行,也能发出API请求返回了。是的,很抱歉其他答案不完整。我编辑了我的答案以包含一个解决方案。嗯,这样请求者就不会等到下一个请求者启动了吗?这是一个有趣的想法,我将尝试一下,看看它是如何工作的。谢谢!不过,如果我们定义
def run(self)
,而不是
req.start()
,我们不应该改为使用
req.run()
吗?我还更新了标题部分,错误地将其与一些不相关的代码一起取出。因此,当使用线程时,通常不调用run方法,run从start方法调用。附带说明。我来自java背景,但我确实看到了这一点[使用Jerubs answer,这可能是一种更为python的解决方案。因此,如果您不想创建thread的子类,您可以改为执行以下操作:def makeRequest(url、标头、负载):#请求的实际处理(抱歉,我似乎不知道如何将代码放入代码块中)
apscheduler
包以一种干净的面向对象的方式实现了这一目标,但确实需要理解一些中间Python原则。有关详细信息,请参阅下面的答案。我尝试了两种解决方案,但问题仍然存在。我认为其背后的原因是请求本身执行所需的时间超过1秒(我试着每5秒运行一次,这样效果很好)