Two-dimensional dict assignment not meeting expectations - python

The function's return not meeting expectations.
My env py2.7.11 centos6.5.
I hope the function return the return like this
{'www.baidu.com': {'3xx': 0, 'response_time': 0.126, '5xx': 0, '4xx': 1},
'www.google.com': {'3xx': 0, 'response_time': 0, '5xx': 0, '4xx': 0}}
But in fact it is return like that. The send_dict['www.google.com']['response_time'] and send_dict['www.google.com']['response_code'] shouldn't be assigned. But why?
{'www.baidu.com': {'3xx': 0, 'response_time': 0.126, '5xx': 0, '4xx': 1},
'www.google.com': {'3xx': 0, 'response_time': 0.126, '5xx': 0, '4xx': 1}}
The Python code:
#!/usr/bin/python
# -*- coding: utf-8 -*-
sink_dict = {'sink_zabbix_monitor_keys': '3xx,4xx,5xx,response_time',
'sink_zabbix_domain_keys': 'www.baidu.com,www.google.com'}
sub_send_dict = dict.fromkeys(sink_dict['sink_zabbix_monitor_keys'].split(','), 0)
send_dict = dict.fromkeys(sink_dict['sink_zabbix_domain_keys'].split(','), sub_send_dict)
def calculate_item(item):
response_code_dict = dict.fromkeys(sink_dict['sink_zabbix_domain_keys'].split(','), 0)
response_time_dict = dict.fromkeys(sink_dict['sink_zabbix_domain_keys'].split(','), 0)
domain = item['domain']
response_code_dict[domain] = int(item['response_code'])
response_time_dict[domain] = float(item['response_time'])
if domain in send_dict:
print domain
if response_time_dict[domain] > float(send_dict[domain]['response_time']):
send_dict[domain]['response_time'] = response_time_dict[domain]
send_dict[domain][str(response_code_dict[domain])[0] + "xx"] += 1
return send_dict
tmp_item = {'domain': 'www.baidu.com', 'response_time': '0.126', 'response_code': '401'}
tmp_item1 = {'domain': 'www.google.com', 'response_time': '0.126', 'response_code': '401'}
tmp_item2 = {'domain': 'www.baidu.com', 'response_time': '0.166', 'response_code': '401'}
print calculate_item(tmp_item)

Here you go:
send_dict = {k: sub_send_dict.copy() for k in sink_dict['sink_zabbix_domain_keys'].split(',')}
This is called dict comprehension. This works because I'm assigning a shallow copy of the dictionary to the key. dict.fromkeys() will assign the value to every key, all keys will share the same sub_send_dict reference.
From the (linked) python docs:
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.

Related

Count values from rowlist divided by key in nested dict

Here is an example dataset
Firstly, I try to create a dict from values in rows:
import csv
who = set()
figure = set()
date = set()
action = []
activity = {'play': 0, 'throw': 0, 'pin': 0, 'tap': 0}
with open(r'ShtrudelT.csv',
mode = 'r') as csv_file:
lines = csv_file.readlines()
for row in lines:
data = row.split(',')
who.add(data[1])
figure.add(data[2])
date.add(data[3][:7])
action.append(data[4].strip())
xdict = dict.fromkeys(who,
dict.fromkeys(figure,
dict.fromkeys(date, activity)))
The result is:
{'Googenhaim': {'Circle': {'2020-04': {'play': 0,'throw': 0, 'pin': 0, 'tap': 0},
'2020-06': {'play': 0, 'throw': 0, 'pin': 0, 'tap': 0},
'2020-05': {'play': 0, 'throw': 0, 'pin': 0, 'tap': 0}},
'Rectangle': {'2020-04': {'play': 0, 'throw': 0, 'pin': 0, 'tap': 0}...}
Secondly, I need to count actions divided by key to analyze data. For example, how many times Googenhaim use Circle by any type of action in every month.
Is there a solution without using Pandas?
import csv
count_dict = {}
with open(r'ShtrudelT.csv',
mode = 'r') as csv_file:
lines = csv_file.readlines()
for row in lines:
data = row.split(',')
key = data[1] + "_" + data[2] + "_" + data[3][:7] + "_" + data[4].strip()
if key in count_dict:
count_dict[key] += 1
else:
count_dict[key] = 1
print("\t".join(["Name", "Shape", "Month", "Action", "Count"]))
for element, count in count_dict.items():
items = element.split("_")
print("\t".join(items) + "\t" + str(count))
We use a dictionary where every key is the combination that we want to count. This combination is formed from name of the user, shape, month and the action. While processing every line, we form the key and store it in the dictionary. If it is encountered for the first time then we insert it or else we update the count.
After all the lines are processed, we can do any kind of post processing we want to do.
Hope that solves it.

Fatterned List in Dict

Like to convert following data into single list in dict. If the dict key already exits in list in the list and value is the same, do not add it.
data1 =
"""
[{'In': ['5,000 MByte']},
{'Out': ['155 MByte', '10,100 MByte']},
{'Total': ['5,000 MByte']},}]
"""
Expected:
[{'In': '5,000 MByte',
'Out': '155 MByte',
'Total': '5,000 MByte'}]
This should work:
data1 = """
[{'In': ['5,000 MByte']},
{'Out': ['155 MByte', '10,100 MByte']},
{'Total': ['5,000 MByte']}]
"""
import ast
data1_dict = {}
for item in ast.literal_eval(data1):
for key in item:
data1_dict[key] = item[key][0]
res = [data1_dict]
print(res)

Appending new items to a Python list with logic operators (Time values)

I'm starting out on Python on a job (I'm used to R) where I have to get daily data from an API that returns the datetime and value (which is a certain number of listeners on a podcast) and then send that data to a bigquery database.
After I split up the date and time, I need to add a new column that indicates which program was playing in that moment. In other words:
if time is >= than 11:00 and <= 11:59 then add a 'program name' value to the row into the column 'program'.
I've ran into several problems, namely the fact that time has been split as strings (could be due to the fact that we use google data studio, which has extremely rigid datetime implementation).
How would you go about it?
if response.status_code == 200:
data = response.text
result = json.loads(data)
test = result
#Append Items
for k in test:
l = []
l.append(datetime.datetime.strptime(k["time"], "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%Y-%m-%d"))
l.append(datetime.datetime.strptime(k["time"], "%Y-%m-%dT%H:%M:%S.%fZ").astimezone(pytz.timezone("America/Toronto")).strftime("%H:%M"))
l.append(k["value"])
You need to have a 'DB' of the programs timetable. See below.
Your loop will call the function below with the time value and you will have the program name.
import datetime
from collections import namedtuple
Program = namedtuple('Program', 'name start end')
PROGRAMS_DB = [Program('prog1', datetime.time(3, 0, 0), datetime.time(3, 59, 0)),
Program('prog2', datetime.time(18, 0, 0), datetime.time(18, 59, 0)),
Program('prog3', datetime.time(4, 0, 0), datetime.time(4, 59, 0))]
def get_program_name(time_val):
for program in PROGRAMS_DB:
if program.start <= time_val <= program.end:
return program.name
data_from_the_web = [{"time": "2019-02-19T18:10:00.000Z", "value": 413, "details": None},
{"time": "2019-02-19T15:12:00.000Z", "value": 213, "details": None}]
for entry in data_from_the_web:
t = datetime.datetime.strptime(entry["time"], "%Y-%m-%dT%H:%M:%S.%fZ").time()
entry['prog'] = get_program_name(t)
for entry in data_from_the_web:
print(entry)
Output
{'prog': 'prog2', 'details': None, 'value': 413, 'time': '2019-02-19T18:10:00.000Z'}
{'prog': None, 'details': None, 'value': 213, 'time': '2019-02-19T15:12:00.000Z'}

InstaBot API Follow not Working

I am using InstaBot Python API its working fine for Instagram Likes, But if i set only follow then nothing is happened. I tried a lot to fix this but did not get Proper solution. Could any one please let me know where i am worng in the code ? Here is my code :
bot = InstaBot(
login = 'xyz',
password = 'xyz',
like_per_day = 0,
comments_per_day = 0,
tag_list = '',
tag_blacklist = ['rain', 'thunderstorm'],
user_blacklist = {},
max_like_for_one_tag= 50,
follow_per_day = 10,
follow_time = 1 * 60,
unfollow_per_day = 0,
unfollow_break_min = 120,
unfollow_break_max = 180,
log_mod = 0,
proxy = '',
comment_list=[
["photo", "picture", "pic", "shot", "snapshot"],
],
# Use unwanted_username_list to block usernames containing a string
## Will do partial matches; i.e. 'mozart' will block 'legend_mozart'
### 'free_followers' will be blocked because it contains 'free'
unwanted_username_list=[
'second', 'stuff', 'art', 'sex', 'food', 'blog',
],
unfollow_whitelist=['example_user_1', 'example_user_2']
)
Please Help me to Fix my problem
Your tag list is empty. You need to set some tags for the bot to search so it can follow the people. I'd also recommend updating your default values so it's a bit easier for you to comprehend the configurations. You can build this up over time when you decide to use different features.
I'd recommend reading over the README.md for instructions on how to use the bot
(assuming this is the one you're using - the configurations look familiar to me)
bot = InstaBot(
login = 'xyz',
password = 'xyz',
like_per_day = 0,
comments_per_day = 0,
tag_list = ['sun', 'sea', 'water'],
tag_blacklist = [],
user_blacklist = {},
max_like_for_one_tag= 50,
follow_per_day = 10,
follow_time = 1 * 60,
unfollow_per_day = 0,
unfollow_break_min = 120,
unfollow_break_max = 180,
log_mod = 0,
proxy = '',
comment_list=[],
unwanted_username_list=[],
unfollow_whitelist=[]
)

python: incrementing values in a tokyo cabinet store

I am using tcdb to hold a large key-value store. The keys are strings representing user IDs, the values are dicts of the form
{'coord':0,'node':0,'way':0,'relation':0}
The store is filled iterating over a data file that has coord, node, way and relation objects, each linked to a specific user. Here's my code for incrementing the fields:
def increment(self,uid,typ):
uid = str(uid)
type = str(typ)
try:
self.cache[uid][typ] += 1
except KeyError:
try:
self.cache[uid][typ] = 1
except KeyError:
try:
print 'creating record for %s' % uid
self.cache[uid] = {'coord':0,'node':0,'way':0,'relation':0}
except KeyError:
print 'something\'s messed up'
This does not work. I end up with a table that has all zero values:
def result(self):
print 'cache is now %i records' % len(self.cache)
for key in self.cache:
print key + ': ' + str(self.cache[key])
yields:
...
4951: {'node': 0, 'coord': 0, 'relation': 0, 'way': 0}
409553: {'node': 0, 'coord': 0, 'relation': 0, 'way': 0}
92274: {'node': 0, 'coord': 0, 'relation': 0, 'way': 0}
259040: {'node': 0, 'coord': 0, 'relation': 0, 'way': 0}
...
Why?
The last exception is never called.
EDIT This code in the first try block:
tempdict = self.cache[uid]
tempdict[typ] = tempdict.get(typ,0) + 1
self.cache[uid] = tempdict
instead of the original
self.cache[uid][typ] += 1
works, but looks really ugly to me.
After this line:
self.cache[uid] = {'coord':0,'node':0,'way':0,'relation':0}
Add this:
self.cache[uid][type] = 1
Also, please don't use type as a variable name as it hides the built-in of the same name.

Categories