I have following module root_file.py. This file contains number of blocks like.
Name = {
'1':'a'
'2':'b'
'3':'c'
}
In other file I am using
f1= __import__('root_file')
Now the requirement is that I have to read values a,b,c at runtime using variables like
for reading a
id=1
app=Name
print f1[app][id]
but getting error that
TypeError: unsubscriptable object
How about
import root_file as f1
id = 1
app = 'Name'
print getattr(f1, app)[id] # or f1.Name[id]
Uh, well, if I understand what you are trying to do:
In root_file.py
Name = {
'1':'a', #note the commas here!
'2':'b', #and here
'3':'c', #the last one is optional
}
Then, in the other file:
import root_file as mymodule
mydict = getattr(mymodule, "Name")
# "Name" could be very well be stored in a variable
# now mydict eqauls Name from root_file
# and you can access its properties, e.g.
mydict['2'] == 'b' # is a True statement
Related
Here's the code I'm trying to run. Works when executed from PyCharm. I set up a cronjob and it worked wonders for weeks. It's now giving a KeyError out of the bloom. Can't find what's wrong since I haven't touched anything in the cronjob.
import csv
import json
import os
import random
import time
from urllib.parse import urlencode
import requests
API_URL = "https://community.koodomobile.com/widget/pointsLeaderboard?"
LEADERBOARD_FILE = "leaderboard_data.json"
def get_leaderboard(period: str = "allTime", max_results: int = 20) -> list:
payload = {"period": period, "maxResults": max_results}
return requests.get(f"{API_URL}{urlencode(payload)}").json()
def dump_leaderboard_data(leaderboard_data: dict) -> None:
with open("leaderboard_data.json", "w") as jf:
json.dump(leaderboard_data, jf, indent=4, sort_keys=True)
def read_leaderboard_data(data_file: str) -> dict:
with open(data_file) as f:
return json.load(f)
def parse_leaderboard(leaderboard: list) -> dict:
return {
item["name"]: {
"id": item["id"],
"score_data": {
time.strftime("%Y-%m-%d %H:%M"): item["points"],
},
"rank": item["leaderboardPosition"],
} for item in leaderboard
}
def update_leaderboard_data(target: dict, new_data: dict) -> dict:
for player, stats in new_data.items():
target[player]["rank"] = stats["rank"]
target[player]["score_data"].update(stats["score_data"])
return target
def leaderboard_to_csv(leaderboard: dict) -> None:
data_rows = [
[player] + list(stats["score_data"].values())
for player, stats in leaderboard.items()
]
random_player = random.choice(list(leaderboard.keys()))
dates = list(leaderboard[random_player]["score_data"])
with open("the_data.csv", "w") as output:
w = csv.writer(output)
w.writerow([""] + dates)
w.writerows(data_rows)
def script_runner():
if os.path.isfile(LEADERBOARD_FILE):
fresh_data = update_leaderboard_data(
target=read_leaderboard_data(LEADERBOARD_FILE),
new_data=parse_leaderboard(get_leaderboard()),
)
leaderboard_to_csv(fresh_data)
dump_leaderboard_data(fresh_data)
else:
dump_leaderboard_data(parse_leaderboard(get_leaderboard()))
if __name__ == "__main__":
script_runner()
Here's the error taht it gives me. Seems like there's a problem with dictionary hence the KeyError.
File "/Users/Rob/PycharmProjects/Koodo/TEST.Json.py", line 75, in <module>
script_runner()
File "/Users/Rob/PycharmProjects/Koodo/TEST.Json.py", line 64, in script_runner
fresh_data = update_leaderboard_data(
File "/Users/Rob/PycharmProjects/Koodo/TEST.Json.py", line 44, in update_leaderboard_data
target[player]["rank"] = stats["rank"]
KeyError: 'triggered123'
Here's the data in JSON file : https://pastebin.com/HQyL4Kyx
It looks to me like the first time your code is run, it caches the leaderboard.
On subsequent runs, it will update the existing leaderboard with the new values, by looping over each of the new entries, finding their username, and looking up that key in the older dictionary. However, if there's a new user, that key will not exist in the old dictionary.
You're getting the error because the player triggered123 is a new user to the leaderboard, and was listed after you first ran the script.
You need to update update_leaderboard_data to handle this case (by checking if the key exists in the dictionary before attempting to access it).
That's because the key named triggered123 is NOT present in the dictionary target.
Source: https://wiki.python.org/moin/KeyError
The problem is that in update_leaderboard_data you iterate over the new data and use them to lookup in the old data. If a new key does not already exists in the old data, you'll get the KeyError.
Try to print the dict target to see if the key triggered123 is in it.
Or use the get method of the dict with a default value: so no error wil be raised, and you'll be able to search this default value in your output.
How can I create a config file with unique only one unique property?
Or are there any loop for checking the config file where I find a duplicated name property value and it gives an exception?
[NAME+TIMESTAMP]
Name=UNIQUE NAME
Property=something
Property1=something1
Property2=something2
[NAME+TIMESTAMP]
Name=UNIQUE NAME
Property=something
Property1=something1
Property2=something2
Due to configParser being dict-like in most things, what we can do here is use the key of the different code-blocks to make sure that there are unique blocks.
Here is a simple test to show it in action:
import configparser
class Container:
configs=[] # keeps a list of all initialized objects.
def __init__(self, **kwargs):
for k,v in kwargs.items():
self.__setattr__(k,v) # Sets each named attribute to their given value.
Container.configs.append(self)
# Initializing some objects.
Container(
Name="Test-Object1",
Property1="Something",
Property2="Something2",
Property3="Something3",
)
Container(
Name="Test-Object2",
Property1="Something",
Property2="Something2",
Property3="Something3",
)
Container(
Name="Test-Object2",
Property1="Something Completely different",
Property2="Something Completely different2",
Property3="Something Completely different3",
)
config = configparser.ConfigParser()
for item in Container.configs: # Loops through all the created objects.
config[item.Name] = item.__dict__ # Adds all variables set on the object, using "Name" as the key.
with open("example.ini", "w") as ConfigFile:
config.write(ConfigFile)
In the above example, I create three objects that contain variables to be set by configparser. However, the third object shares the Name variable with the second Object. That means that the third one will "overwrite" the second while writing the .ini file.
example.ini:
[Test-Object1]
name = Test-Object1
property1 = Something
property2 = Something2
property3 = Something3
[Test-Object2]
name = Test-Object2
property1 = Something Completely different
property2 = Something Completely different2
property3 = Something Completely different3
EDIT:
I can print rev['contributor'] for a while but then every try to access rev['contributor'] returns the following
TypeError: string indices must be integers
ORIGINAL POST:
I'm trying to extract data from an xml using xml to dict with the code:
import xmltodict, json
with open('Sockpuppet_articles.xml', encoding='utf-8') as xml_file:
dic_xml = xmltodict.parse(xml_file.read(), xml_attribs=False)
print("parsed")
for page in dic_xml['mediawiki']['page']:
for rev in page['revision']:
for user in open("Sockpuppet_names.txt", "r", encoding='utf-8'):
user = user.strip()
if 'username' in rev['contributor'] and rev['contributor']['username'] == user:
dosomething()
I get this error in the last line with the if-statement:
TypeError: string indices must be integers
Weird thing is, it works on another xml-file.
I got the same error when the next level has only one element.
...
## Read XML
pastas = [os.path.join(caminho, name) for name in os.listdir(caminho)]
pastas = filter(os.path.isdir, pastas)
for pasta in pastas:
for arq in glob.glob(os.path.join(pasta, "*.xml")):
xmlData = codecs.open(arq, 'r', encoding='utf8').read()
xmlDict = xmltodict.parse(xmlData, xml_attribs=True)["XMLBIBLE"]
bible_name = xmlDict["#biblename"]
list_verse = []
for xml_inBook in xmlDict["BIBLEBOOK"]:
bnumber = xml_inBook["#bnumber"]
bname = xml_inBook["#bname"]
for xml_chapter in xml_inBook["CHAPTER"]:
cnumber = xml_chapter["#cnumber"]
for xml_verse in xml_chapter["VERS"]:
vnumber = xml_verse["#vnumber"]
vtext = xml_verse["#text"]
...
TypeError: string indices must be integers
The error occurs when the book is "Obadiah". It has only one chapter.
Cliking CHAPTER value we see the following view. Then it's supposed xml_chapter will be the same. That is true only if the book has more then one chapter:
But the loop returns "#cnumber" instead of an OrderedDict.
I solved that converting the OrderedDict to List when has only one chapter.
...
if len(xml_inBook["CHAPTER"]) == 2:
xml_chapter = list(xml_inBook["CHAPTER"].items())
cnumber = xml_chapter[0][1]
for xml_verse in xml_chapter[1][1]:
vnumber = xml_verse["#vnumber"]
vtext = xml_verse["#text"]
...
I am using Python 3,6.
I have a file to read and a dictionary.
If the file says:
sort-by username
I want the dictionary to be
d = {'sort-by': 'username'}
if the file says :
sort-by name
then I want the dictionary to be
d = {'sort-by': 'name'}
right now, I have:
if 'user' in line:
d['sort-by'] = 'username'
else:
d['sort-by'] = 'name'
however, even though the file says sort-by username, I keep getting
d = {'sort-by': 'name'}
why is this?
print dict(map(str.split,open("some_file.txt")))
assuming your file actually looks like your example
if you have any control it may be more appropriate to store your data as json
I am writing a Python CGI that gets certain field values from a HTML page, I am at a point where I need to transform those input values to make them match table values of a database and get data from it.
For example, if the field value of my UI is 'critic' then it should be transformed to '8_critic' to match the database table value.
How can I do this please ?
Something like this maybe ?
#!C:\Python27\python.exe -u
import cgi
import json
import cgitb
print "Content-type: application/json\n\n"
fs = cgi.FieldStorage()
def transform(fs):
for key in fs.keys():
if key == 'critic' :
#key = '8_critic'
elif key == 'somthing_else' :
#key = 'another_thing'
Any help would be appreciated.
The best way for me would me to have a translation table:
tr = { 'critic' : '8_critic', 'foo' : 'bar' }
and to make a new dictionnary by comprehension:
nfs = { tr[k]:fs[k] for k in fs }
Here, I assumed that you did not care about the FieldStorage at this point. If it isn't so, you can still do something like that:
nfs = cgi.FieldStorage()
for k in fs:
nfs[ tr[k] ] = fs[k]