1

I want to use aiohttp as a simple http server to response to client's http get result:
client sends a http get request like this
curl 'http://localhost:8081/query=192.168.1.1,18.9.8.1,10.3.4.5',
then my simple server response a result like this
[{'ip': '192.168.1.1'}, {'ip': '18.9.8.1'}, {'ip': '10.3.4.5''}],
but actually the reponse loop 10.3.4.5 for 3 times, it's strange:
[{'ip': '10.3.4.5'}, {'ip': '10.3.4.5'}, {'ip': '10.3.4.5'}]
my code is as below:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


import asyncio
from aiohttp import web


async def index(request):
    await asyncio.sleep(0)
    return web.Response(body=b'''Usage Example: curl "http://xxxx/query=ip1[,ip2...]" ''')

async def query(request):
    await asyncio.sleep(0)
    ip_list = list(request.match_info['many_ip'].split(','))
    text=[]
    # d={"ip":None,"problem_appearance":"cpu.idle <= 10%","problem_rootcase":"来自10.1.1.2的如下慢SQL导致","begin_time":"2017-07-07 10:59:00","end_time":"2017-07-07 11:00:00","suggest_solution":"null"}
    d={"ip":None}
    for ip in ip_list:
        d["ip"]=ip
        print(d)
        text.append(d)

    print(text)
    return web.Response(body=str(text))

async def init(loop):
    port='8081'
    app = web.Application(loop=loop)
    app.router.add_route('GET', '/', index)
    app.router.add_route('GET', '/query={many_ip}', query)
    srv = await loop.create_server(app.make_handler(), '127.0.0.1', port)
    print('Server started at http://127.0.0.1:{port}...'.format(port=port))
    return srv

loop = asyncio.get_event_loop()
loop.run_until_complete(init(loop))
loop.run_forever()
leafonsword
  • 2,735
  • 3
  • 16
  • 20

1 Answers1

3

The variable d contains reference ("pointer") to dictionary. The text.append(d) statement just add reference of the same dictionary into the list. So after N iterations you have N same references to d in the list.

If you change you loop into something like this:

for ip in ip_list:
    d["ip"]=ip
    text.append(d)
    print(text)

you should see on the console:

[{'ip': '192.168.1.1'}]
[{'ip': '18.9.8.1'}, {'ip': '18.9.8.1'}]
[{'ip': '10.3.4.5'}, {'ip': '10.3.4.5'}, {'ip': '10.3.4.5'}]

It's because the d is a reference and when you change something through reference you change it everywhere where you use the same reference.

To fix your problem you should write something like this:

for ip in ip_list:
    d = {"ip" : ip}
    print(d)
    text.append(d)

In this case in every iteration it creates a new dictionary and reference to it is saved into d.

In case that you need use the d already created outside of your loop then you should use the copy() method of a dictionary. It creates a shallow copy of the dictionary saved in the d (more information about shallow and deep copy you can find here: Understanding dict.copy() - shallow or deep?).

Qeek
  • 1,910
  • 22
  • 28