Get a parameter of a file .txt using python - python

I'm trying to get parameters of a .txt like that:
a=10
b=15
c=20
How can i do a function called get() that takes from this file called parameters.txt the parameter b and return 15??
It's to build a module that works like a getter of parameters.
To simplify and explain information: the .txt conatains parameters with and int value. The get() function will obtain the integer value associated to the parameter.

Since you say you want "to build a module that works like a getter of parameters", you should just parse the whole file into an internal dictionary:
class Config(dict):
def __init__(self, file_name):
with open(file_name) as f:
for line in f:
key, value = line.strip().split("=")
self[key] = value
Example usage:
c = Config("test.txt")
print(c)
# {'a': '10', 'b': '15', 'c': '20'}
print(c['b'])
# 15
If all your values are numerical, you might want to modify this to do self[key] = float(value) or similar. Otherwise you might want to define a try_parse_numeric function:
def try_parse_numeric(s):
try:
return int(s)
except ValueError:
pass
try:
return float(s)
except ValueError:
pass
return s
class Config(dict):
def __init__(self, file_name, value_parser=try_parse_numeric):
self.value_parser = value_parser
with open(file_name) as f:
for line in f:
key, value = line.strip().split("=")
self[key] = self.value_parser(value)
And if it gets more complicated than that, you probably want to use configparser instead of rolling your own.

def get(param):
with open(filename, "r") as infile: #Read file
for line in infile: #Iterate over each line
if line.startswith(param): #Check if line starts with input param
return line.split("=")[1] #Return Value
print(get("b"))

def get(par):
with open("parameters.txt",'r') as file:
return next(e for e in file.readlines() if par in e).split("=")[1]
Try this

Something like this sould work:
def get(filename,variable):
with open(filename) as f:
for line in f.readlines():
if line[:len(variable)] == variable:
return line.split("=")[-1]
return None
print(get("test.txt","b"))

Related

Why isn't this method assigning the variable as expected?

I have a method to read from a file and assign the contents to a variable.
def recall_data(self, file, d):
try:
with open(file) as f:
d = json.load(f)
print(d)
except FileNotFoundError:
print('No File!')
I call the method and know that the value of d is assigned to the contents of the file (a dictionary). However, the code doesn't store the value of d in the variable I pass as d.
self.recall_data(self.file_name, self.data)
This is my method call. self.data is an empty dictionary. I don't understand why it isn't assigning self.data with the contents of self.file_name.
You aren't passing the argument for reference.
That's how the argument passage for value works in Python:
var = 'hey'
def foo(arg):
arg = 'yay'
print(arg)
foo(var) # 'yay'
print(var) # 'hey'
In your case, you can do this:
def recall_data(self, file, d: list): # d is a list with one element
try:
with open(file) as f:
d[0] = json.load(f) # This way you are really editing the variable in the global scope
print(d[0])
except FileNotFoundError:
print('No File!')
Notice that the d argument in this case MUST be of type list, so self.data must too.
If you want to know more about this method, you can read the answers to this question.
Otherwise you can do something like this:
def recall_data(self, file, d):
try:
with open(file) as f:
d = json.load(f)
print(d)
return d
except FileNotFoundError:
print('No File!')
self.data = self.recall_data(self.file_name, self.data) # The returned value will be stored into self.data
Notice that you should never use the first way I suggested above, it was just to solve the problem without changin so much your code.

Python 2.7 problems with sub-classing dict and mirroring to json

So I am trying to create a class that behaves like a dict but also copies itself to a .json file whenever a change is made to the dict. I've got it working for the most part; but where I have trouble is when I append something to a list inside the dict; it updates the dict but not the .json file associated with the dict.
I am sorry for the lengthy code block, I tried to condense as much as possible but it still turned out fairly lengthy.
import json
import os.path
class JDict(dict):
def __init__(self, filepath, *args, **kwargs):
if str(filepath).split('.')[-1] == 'json':
self.filepath = str(filepath)
else:
self.filepath = str('{}.json'.format(filepath))
if os.path.isfile(self.filepath):
super(JDict, self).__init__(self.read())
else:
super(JDict, self).__init__(*args, **kwargs)
self.write()
def __setitem__(self, key, value):
dict.__setitem__(self, key, value)
self.write()
def write(self):
with open(self.filepath, 'w') as outfile:
json.dump(self, outfile, sort_keys = True, indent = 4,
ensure_ascii=False)
def read(self):
with open(self.filepath, 'r') as infile:
jsonData = json.load(infile)
self = jsonData
return self
def parseJson(filepath):
with open(filepath, 'r') as infile:
jsonData = json.load(infile)
return jsonData
test = JDict("test.json", {
"TestList": [
"element1"
]
})
test["TestList"].append("element2")
try:
if test["TestList"][1] == parseJson("test.json")["TestList"][1]:
print 'Success'
except IndexError:
print 'Failure'
So the reason I was having trouble was because setitem isn't called on the dict (or even on a list for that matter) when you append an element to a member list.
Soooo...if anyone else is having this issue; I ended up sub-classing both list and dict datatypes and making them sort of helper classes to a new class called QJson
all lists and dicts under the helper class QJson get converted to JDicts and JLists respectively.
and QJson is itself a dict
The code is REALLY long and monolithic at this point so here is a link to my github enjoy. :)

How to use the same line of code in all functions?

I am newbie in Python.
I wonder if it is possible that all functions inherit the same line of code?
with open(filename, 'r') as f: as this line of code is the same in all three functions. Is it possible to inherit the code without using classes?
I tried to find the answer on stackoverflow and python documentation, but with no luck.
def word_count(filename):
with open(filename, 'r') as f:
return len(f.read().split())
def line_count(filename):
with open(filename, 'r') as f:
return len(f.read().splitlines())
def character_count(filename):
with open(filename, 'r') as f:
return len(f.read())
The common code in your case is
with open(filename, 'r') as f:
contents = f.read()
So just move it to its own function:
def get_file_contents(filename):
with open(filename, 'r') as f:
return f.read()
def word_count(filename):
return len(get_file_contents(filename).split())
def line_count(filename):
return len(get_file_contents(filename).splitlines())
def character_count(filename):
return len(get_file_contents(filename))
What I've done in the past is split the code out into another function, in your example
with open(filename, 'r') as f:
f.read()
Is common within all of your methods, so I'd look at rewriting it like so.
def read_file(filename):
with open(filename, 'r') as f:
return f.read()
def word_count(filename):
return len(read_file(filename).split())
def line_count(filename):
return len(read_file(filename).splitlines())
def character_count(filename):
return len(read_file(filename))
I would use a class:
class Count:
""" Object holds everything count-related """
def __init__(self, filename):
""" specify filename in class instance """
with open(filename, 'r') as f:
self.content = f.read()
def word_count(self):
return len(self.content.split())
def line_count(self):
return len(self.content.splitlines())
def character_count(self):
return len(self.content)
file = Count("whatever.txt")
print(file.word_count())
print(file.line_count())
print(file.character_count())
What you do differently is after you open the file, so if I were in your shoes, I would write a function which takes another function that is executed after the file is opened.
Let's illustrate this in an example:
>>> def operate_file(filename, func):
... with open(filename, 'r') as f:
... return func(f)
>>> def line_count(f):
... return len(f.read().splitlines())
>>> def word_count(f):
... return len(f.read().split())
>>> def character_count(f):
... return len(f.read())
>>> print operate_file('/tmp/file.txt', line_count)
1200
>>> print operate_file('/tmp/file.txt', word_count)
2800
>>> print operate_file('/tmp/file.txt', character_count)
29750
I would recommend decorators. It's sort of like the making the repeated line of code into a function, but since you are going to call that function on each input anyway, decorators can let you just write the functions as id f was the input.
The #open_file is a shorthand for word_count=open_file(word_count).
here is a good place to read more about python decorators.
def open_file(func):
def wrapped_func(filename):
with open(filename, 'r') as f:
return func(f)
return wrapped_func
#open_file
def word_count(f):
return len(f.read().split())
#open_file
def line_count(f):
return len(f.read().splitlines())
#open_file
def character_count(f):
return len(f.read())
It depends on, what you want to do with the results of your 3 functions. Every function is opening the same file. That happens 3 times just to get 3 different properties.
One good solution would be a class. But another would be to rearange your functions to just one. That could return a dictionary or named tuple with the results.
It would look something like this:
def file_count(filename):
with open(filename, 'r') as f:
content = f.read()
properties = {}
properties['words'] = len(content.split())
properties['lines'] = len(content.splitlines())
properties['chars'] = len(content)
return properties

TypeError: 'top_list' object does not support indexing

I would like to print out the list sorted by the second element.
TypeError: 'top_list' object does not support indexing
Is there anyone that can help me?
class top_list(object):
def __init__(self, name, hit_rate):
self.name = name
self.hit_rate = float(hit_rate)
def __str__(self):
return "{0} {1}".format(self.name, self.hit_rate)
def top_ten():
"""Prints out the list"""
top10 = []
file = open("high_score.txt")
for i in range(0,1):
x = file.readlines()
for line in x:
line = line.split(",")
lista = top_list(line[0], float(line[1]))
top10.append(lista)
a = sorted(top10, key=lambda line: line[1])
print(a)
In your code
a = sorted(top10, key=lambda line: line[1])
you are trying to access the top_list element using subscript notation. If that is what you want to do, implement a __getitem__ method. __getitem__ allows you to use the subscript operator - list[1] translates to list.__getitem__(1).
def self.__getitem__(self, key):
if key == 1:
return self.name
else:
return self.hit_rate
Or modify the lambda function to access the element you want without using a subscript:
a = sorted(top10, key=lambda line: line.hit_rate)
Also note that using context manager for file is safer and more pythonic. You can also read the lines by iterating over the Python file object:
with open('high_score.txt', 'r') as file:
for line in file:
...
but extra caution needs to be taken to handle newlines (stripping them possibly).

Error accessing class objects in python

I am having some problem accessing class instances. I am calling the class from a procedure, name of instance is defined in some variable. I want the instance name to be created of that value and then want to access it, but when i access it is giving error. Can some one please help to resolve this issue.
class myclass:
def __init__(self,object):
self.name = object
def mydef():
global a1
b = "a1"
b = myclass(b)
mydef()
print a1.name
Second Problem:
In my actual script, I have to create a large number of such instances from this function (around 100). So defining their name as global would be painful, is there a way i could access those instances outside function without having to declare them as global.
Modification:
class myclass:
def __init__(self,object,typename):
self.name = object
self.typeid = typename
def mydef():
file_han = open(file,"r")
while True:
line = file_han.readline()
if not line:
break
start = line.find('"')
end = line.find('"',start+1)
string_f = line[start+1:end]
myclass(string_f,'a11')
mydef(file)
print def.name
print def.typeid
File Contents are :
a11 "def"
a11 "ghi"
a11 "eff"
Here's how I'd do it. I don't know why you're messing around with globals, if you'd care to explain, I'll update my answer.
class Myclass(object):
def __init__(self, name):
self.name = name
def mydef():
return Myclass("a1")
a1 = mydef()
print a1.name
Gather your instances in a list:
instances = []
for x in range(1000):
instances.append(Myclass("Instance {0}".format(x)))
print instance[42].name
Note the changes:
Class names should be capitalized
Use object as the base class of your classes (since python 2.2, but no longer necessary in 3.x)
Don't shadow the built-in object with your parameter name
Just use the string "a1" directly as a parameter instead of assigning it to a variable
Return something from the function instead of passing the result by global variable
RE: Comment
You haven't said anything about the format of these files, so I'll just give an example where the file to be read contains one class name per line, and nothing else:
def mydef(filename):
ret = []
with open(filename) as f:
for line in f:
# Call `strip` on line to remove newline and surrounding whitespace
ret.append(Myclass(line.strip()))
return ret
So if you have several files and wish to add all your instances from all your files to a large list, do it like this:
instances = []
for filename in ["myfile1", "myfile2", "myfile3"]:
instances.extend(mydef(filename))
RE: OP Edit
def mydef(filename):
ret = []
with open(filename, "r") as file_han:
for line in file_han:
string_f = line.split('"')[1]
ret.append(Myclass(string_f))
return ret
i = mydef("name_of_file")
RE: Comment
Oh, you want to access them by name. Then return a dict instead:
def mydef(filename):
ret = {}
with open(filename, "r") as file_han:
for line in file_han:
string_f = line.split('"')[1]
ret[string_f] = Myclass(string_f)
return ret
i = mydef("name_of_file")
print i["ghi"].name # should print "ghi"
RE: Comment
If I understand you correctly, you want to have it both ways -- index by both line number and name. Well then why don't you return both a list and a dictionary?
def mydef(filename):
d = {}
L = []
with open(filename, "r") as file_han:
for line in file_han:
string_f = line.split('"')[1]
instance = Myclass(string_f)
d[string_f] = instance
L.append(instance)
return L, d
L, d = mydef("name_of_file")
print d["ghi"].name
print L[3]
print L.index(d["ghi"])
You could use class as repository for your instances, for example
class Named(object):
def __init__(self,name):
self.name = name
def __new__(cls,name):
instance = super(type,cls).__new__(cls,name)
setattr(cls,name,instance)
return instance
def __repr__(self):
return 'Named[%s]'%self.name
Named('hello')
Named('x123')
Named('this is not valid attribute name, but also working')
print(Named.hello,Named.x123,getattr(Named,'this is not valid attribute name, but also working'))

Categories

Resources