How to write a dictionary to a .py file? - python

I have a dictionary in "albums_data.py" and "album.py" as main program.
I need to update the add_one() function in main program to write the actual state of dictionary in to "albums_data.py" and save it after some data is added to dictionary (using the add_one() function).
Here is the source code:
albums_data.py
albums= {}
albums["Adele"]="21"
albums["Michael Jackson"]="Thriler"
albums["Lady Gaga"]="The Fame"
album.py
import tkinter
from albums_data import *
root=tkinter.Tk()
root.title("DICT example")
#Functions
def show_all():
#clear the listbox
lb_music.delete(0,"end")
#iterate throught the keys and add to the listbox
for artist in albums:
lb_music.insert("end",artist)
def show_one():
artist=lb_music.get("active") #active is clicked field
album=albums[artist]
msg=artist+" - "+album
lbl_output["text"]=msg #Ready is replaced with msg
def add_one():
info=txt_input.get()
split_info=info.split(",") #list is created after is separated with ","
artist=split_info[0]
album=split_info[1]
albums[artist]=album
show_all()
txt_input.delete(0,"end")
#write to .py file (not worked to txt also) ->permission denied
f = open("albums_data.py","w")
f.write( str(albums) )
f.close()
#GUI
lbl_output=tkinter.Label(root,text="Ready")
lbl_output.pack()
txt_input=tkinter.Entry(root)
txt_input.pack()
lb_music=tkinter.Listbox(root)
lb_music.pack()
btn_show_all=tkinter.Button(root,text="Show all",command=show_all)
btn_show_all.pack()
btn_show_one=tkinter.Button(root,text="Show one",command=show_one)
btn_show_one.pack()
btn_add_one=tkinter.Button(root,text="Add one",command=add_one)
btn_add_one.pack()
root.mainloop()

Use JSON.
import json
d = { "hello": "world" }
with open('state.json', 'w') as f:
json.dump(d, f)
with open('state.json', 'r') as f:
d2 = json.load(f)
assert d == d2

Related

Python - changing content of .txt files from folder and saving in new folder

I need to change some key words in multiple .txt files, using dictionary strucure for this. Then, save changed files in new localization. I write code attached below, but when I run it is warking all the time, and when I break it there is only one empty file cretead.
import os
import os.path
from pathlib import Path
dir_path = Path("C:\\Users\\myuser\\Documents\\scripts_new")
#loading pair of words from txt file into dictionary
myfile = open("C:\\Users\\myuser\\Desktop\\Python\\dictionary.txt")
data_dict = {}
for line in myfile:
k, v = line.strip().split(':')
data_dict[k.strip()] = v.strip()
myfile.close()
# Get the list of all files and directories
path_dir = "C:\\Users\\myuser\\Documents\\scripts"
# iterate over files in
# that directory
for filename in os.listdir(path_dir):
f = os.path.join(path_dir, filename)
name = os.path.join(filename)
text_file = open(f)
#read whole file to a string
sample_string = text_file.read()
# Iterate over all key-value pairs in dictionary
for key, value in data_dict.items():
# Replace key character with value character in string
sample_string = sample_string.replace(key, value)
with open(os.path.join(dir_path,name), "w") as file1:
toFile = input(sample_string)
file1.write(toFile)
I have found a solution, with a little different approach. Maybe this code might be usefull for someone:
import os
#loading pair of words from txt file into dictionary
myfile = open("C:\\Users\\user\\Desktop\\Python\\dictionary.txt")
data_dict = {}
for line in myfile:
k, v = line.strip().split(':')
data_dict[k.strip()] = v.strip()
myfile.close()
sourcepath = os.listdir("C:\\Users\\user\\Documents\\scripts\\")
for file in sourcepath:
input_file = "C:\\Users\\user\\Documents\\scripts\\" + file
print('Conversion is ongoing for: ' + input_file)
with open(input_file, 'r') as input_file:
filedata = input_file.read()
destination_path = "C:\\Users\\user\\Documents\\scripts_new\\"+ file
# Iterate over all key-value pairs in dictionary
for key, value in data_dict.items():
filedata = filedata.replace(key,value)
with open(destination_path,'w') as file:
file.write(filedata)
Hmmm... I think your problem might actually be use of the line
toFile = input(sample_string)
As that'll halt the program awaiting a user input
Anyway, it could probably do with a little organisation into functions. Even this below is a bit... meh.
import os
import os.path
from pathlib import Path
dir_path = Path("C:\\Users\\myuser\\Documents\\scripts_new")
# -----------------------------------------------------------
def load_file(fileIn):
#loading pair of words from txt file into dictionary
with open(fileIn) as myfile:
data_dict = {}
for line in myfile:
k, v = line.strip().split(':')
data_dict[k.strip()] = v.strip()
return data_dict
# -----------------------------------------------------------
def work_all_files(starting_dir, moved_dir, data_dict):
# Iterate over files within the dir - note non recursive
for filename in os.listdir(starting_dir):
f = os.path.join(starting_dir, filename)
with open(f, 'r') as f1:
#read whole file to a string
sample_string = f1.read()
new_string = replace_strings(sample_string, data_dict)
with open(os.path.join(moved_dir, filename), "w") as file1:
file1.write(new_string)
# -----------------------------------------------------------
def replace_strings(sample_string, data_dict):
# Iterate over all key-value pairs in dictionary
# and if they exist in sample_string, replace them
for key, value in data_dict.items():
# Replace key character with value character in string
sample_string = sample_string.replace(key, value)
return sample_string
# -----------------------------------------------------------
if __name__ == "__main__":
# Get the dict-val pairings first
data_dict = load_file("C:\\Users\\myuser\\Desktop\\Python\\dictionary.txt")
#Then run over all the files within dir
work_all_files("C:\\Users\\myuser\\Documents\\scripts", "C:\\Users\\myuser\\Documents\\new_scripts", data_dict)
We could have housed all this in a class and then transported a few variables around using the instance (i.e. "self") - would have been cleaner. But first step is learning to break things into functions.

How to make json file a list in Python

as said, I'd like to open a json file and make it into a list, in order to append new elements to it and then dump all back into the json file.
Here is my code(the commented part is what I previously tried):
class Carta:
def __init__(self,filename):
self.__filename = filename
self.__lista = []
# try:
# f = open(self.__filename,"r")
# except:
# f = open(self.__filename, "w")
# f.close()
# f = open(self.__filename, "r")
with open(self.__filename) as file:
self.__lista = json.load(file)
# read=json.load(f)
# for c in leggi:
# self.__lista.append(c)
# print(self.__lista)
# f.close()
def add(self, c):
self.__lista.append(c)
def save(self):
f = open(self.__filename, "w")
for c in self.__lista:
f.write("%s\n" % str(c))
f.close()
It wouldn't work if you read from a JSON file, json list and then write custom string. Because next time you read the JSON file it's gonna fail.
So, during write/save you should make it json itself. Here's the code the explains how to do it.
import json
class Carta:
def __init__(self, filename):
self.__filename = filename
self.__lista = list()
self.read_from_json_file()
def read_from_json_file(self):
with open(self.__filename) as file:
self.__lista = json.load(file)
def write_to_json_file(self):
with open(self.__filename, 'w') as f:
json.dump(self.__lista, f)
def add(self, value):
self.__lista.append(value)
The reason you should use with open(filename, mode) as f: instead of f = open(filename) is because at the end of with block the file is automatically closed. Otherwise you've to call f.close() every time you open a file.
json.load - reads json data from file, converts to python data type/structure.
json.dump - read python data type/structure, converts it into string and stores it in the file (file handle) and saves the file.
Using pdb to trace errors
import json
import pdb
class Carta:
def __init__(self, filename):
self.__filename = filename
self.__lista = list()
self.read_from_json_file()
def read_from_json_file(self):
pdb.set_trace() # to pause execution and start debugger
# When paused,
# type n to continue to next line,
# type c to continue execution or to continue to the next loop
# type b <file_name>:<line_number> to add another break point, where <file_name> and <line_number> are place holders
# Example, b /home/username/hello.py:43, will add breakpoint at 43 line of hello.py in /home/username path
# type q to quit debugger and halt execution
with open(self.__filename) as file:
self.__lista = json.load(file)
def write_to_json_file(self):
with open(self.__filename, 'w') as f:
json.dump(self.__lista, f)
def add(self, value):
# Second breakpoint
pdb.set_trace()
self.__lista.append(value)
Or just run your file with
python -m pdb file.py and then add breakpoints. It will pause in the first line itself and return you a (pdb) console where you can add breakpoint.
import json
#read from file
with open("demofile.txt", "r") as f: x = f.read()
#parse
y = json.loads(x)
#edit
y["user"] = { "fname": "John", "lname": "Who"}
#save to file
with open("demofile.txt", "w") as f: f.write(json.dumps(y))
https://repl.it/#KrzysztofPecyna/PythonJsonExample
To read JSON from a file:
import json
with open('data.txt') as json_file:
data = json.load(json_file)
To add new data:
data['key'] = "value"
To write JSON to a file:
with open('data.txt', 'w') as outfile:
json.dump(data, outfile)

Python script need to save output to text file

I have peiced together some code from the internet to capture pressed keys and the current active window title and am trying to write the output of the python script to a text file.
The script works fine in the IDLE console and prints pressed keys and logs any change in the current active window.
from pynput.keyboard import Key, Listener
import time
from win32gui import GetWindowText, GetForegroundWindow
import datetime
from threading import Thread
def on_press(key):
print ('{0} pressed'.format(key))
def on_release(key):
('{0} release'.format(key))
if key == Key.esc:
return False
def get_titles():
current_title = None
while True:
moment2 = datetime.datetime.now().strftime("%d-%b-%Y [ %H:%M:%S ]")
new_title = GetWindowText(GetForegroundWindow())
if new_title != current_title:
if len(new_title) > 0:
#logging.info(" Moved to : " + new_title)
current_title = new_title
time.sleep(0.1)
#print(new_title)
ff= (moment2 + " : " + "Moved T0 : "+ new_title)
print (ff)
I am looking for a simple way to write the outputs i can see in the console to a text file. It is probably very simple but i am very much a beginner. Thanks
Python has a native open() function, no import needed, which allows you to handle files. This function "loads" the file into memory, and can be set into various modes:
open("filename.txt", "a"), appending the content to a new line;
open("filename.txt", "w"), overwriting the content; and
open("filename.txt", "r"), setting it to read-only.
open("filename.txt", "x"), to create a file.
You can add a "+" to each of this modes ("a+", "w+"), if you want the file to be created if it doesn't already exist.
You define the file in memory to a variable as such: a = open("filename.txt", "w"), and can then text = a.read() to load the content of the file to a string, or a.readlines() to load the strings into an array, split per \n.
Use a.write("Your desired output") to save the content to the file, if the file is in write or append modus.
Edit:
Try to only open files for as long as they are actually needed.
with open("filename.txt", "r") as f:
file_contents = f.read()
# file_contents = "This file contains\nvery important information"
file_lines = f.readlines()
# file_lines = ["This file contains", "very important information"]
# Similar to file_lines = file_contents.split("\n")
in order to avoid blocking other parts of your program, and avoid corrupting your files if Python crashes unexpectedly.
Just add
with open('textfile.txt', 'a+') as f:
f.write(ff)
a option is for appending to a file and + means that if the file is not there just create one with the specified name.
EDIT:
def on_press(key):
print ('{0} pressed'.format(key))
with open('textfile.txt', 'a+') as f:
f.write(ff)
EDIT 2:
def on_press(key):
print ('{0} pressed'.format(key))
k = key + '\n'
with open('textfile.txt', 'a+') as f:
f.write(key)
# and in get_titles()
ff= (moment2 + " : " + "Moved T0 : "+ new_title + '\n')
with open('textfile.txt', 'a+') as f:
f.write(ff)
try this when run program in console
python your_script.py > path_to_output_file/outpot.txt
in case '>' not work then try '>>'

Running a script for many files of the same extension and writing the results to a text file

I'm trying to write a script to extract data from a number of files in a directory with the extension ".tp6" and then write all of that data to a single text file.
It's able to get data from each file correctly and print them to the terminal, but I haven't been able to 'pass' each data point to another function that writes it to a text file.
Any ideas? Thank you!
import glob
import os
import Tkinter
import tkFileDialog
root = Tkinter.Tk()
root.withdraw()
dir_path = tkFileDialog.askdirectory()
os.chdir(dir_path)
def main():
for file_path in glob.glob('*.tp6'):
uncovext(file_path)
def main2():
for file_path in glob.glob('*.tp6'):
totext(uncovext)
#find and print data from each .tp6 file - this part works correctly
def uncovext(file_path):
for line in open(file_path):
if line.startswith(' UNCONVOLVED INTEGRATED RADIANCE'):
text = line[36:47]
number = float(text) * 10000
print('%.3f' % number)
def totext(uncovext):
with open("output.txt", "a") as f:
f.write(uncovext)
f.close()
if __name__ == '__main__':
main()
main2()
I think it was a matter of naming: if you change your input parameter of totext function to p_uncovext for example, it should work. You need also to call the function to text on your loop.
import glob
import os
import Tkinter
import tkFileDialog
root = Tkinter.Tk()
root.withdraw()
dir_path = tkFileDialog.askdirectory()
os.chdir(dir_path)
def main():
for file_path in glob.glob('*.tp6'):
uncovext(file_path)
#find and print data from each .tp6 file - this part works correctly
def uncovext(file_path):
for line in open(file_path):
if line.startswith(' UNCONVOLVED INTEGRATED RADIANCE'):
text = line[36:47]
number = float(text) * 10000
totext('%.3f' % number)
def totext(p_uncovext):
with open("output.txt", "a") as f:
f.write(p_uncovext)
f.close()
if __name__ == '__main__':
main()
You have a couple of problems. First uncovext doesn't save the data it parses from the input file. After printing to the screen, it is just thrown away. You could collect it into a list and return that for further processing. Then, you call the writer in a second function and you don't have any way for main to let main2 know what the data is.
An easy fix is a single function that calls uncovext and uses its result to call totext.
import glob
import os
import Tkinter
import tkFileDialog
root = Tkinter.Tk()
root.withdraw()
dir_path = tkFileDialog.askdirectory()
os.chdir(dir_path)
def main():
for file_path in glob.glob('*.tp6'):
totext(uncovext(file_path))
#find and print data from each .tp6 file - this part works correctly
def uncovext(file_path):
output = []
for line in open(file_path):
if line.startswith(' UNCONVOLVED INTEGRATED RADIANCE'):
text = line[36:47]
number = float(text) * 10000
output.append('%.3f\n' % number)
return output
def totext(uncovext):
with open("output.txt", "a") as f:
f.writelines(uncovext)
if __name__ == '__main__':
main()
You could also rewrite your parser as a generator and write code that I find more self-explanatory (that's just me though...)
def main():
with open('output.txt', 'a') as f:
for file_path in glob.glob('*.tp6'):
f.writelines(uncovext(file_path))
#find and print data from each .tp6 file - this part works correctly
def uncovext(file_path):
for line in open(file_path):
if line.startswith(' UNCONVOLVED INTEGRATED RADIANCE'):
text = line[36:47]
number = float(text) * 10000
yield '%.3f\n' % number

How do I write to the file I selected using filedialog.asksaveasfile?

I am trying to write to a file that I just created using the filedialog.asksaveasfile. I set the mode to 'w'. Do I have to open the file again or something?
f = filedialog.asksaveasfile(mode='w', defaultextension=".csv")
keyList = []
for n in aDict.keys():
keyList.append(n)
keyList = sorted(keyList, key=operator.itemgetter(0,1))
csvWriter = csv.writer(f)
for key in keyList:
sal1 = aDict[(key[0],key[1])][0]
sal2 = aDict[(key[0],key[1])][1]
csvWriter.writerow(key[0], key[1], sal1, sal2)
f.close()
You can simply use the write function of the reference (of type _io.TextIOWrapper) returned by the asksaveasfile function.
For example
from tkinter import filedialog, Tk
root = Tk().withdraw()
file = filedialog.asksaveasfile(mode='w', defaultextension=".csv")
if file:
file.write("Hello World")
file.close()
Note that the object returned by the asksaveasfile function is of the same type or class of the object returned by the built-in open function. Note also that the same function returns None, if Cancel is pressed when the dialog pops up.

Categories