saving and deleting fileI/O - file-io

Two part question.
First, how can i change this(i've tried using 'for' but i cant figure it out) so that it saves like;
'key value' instead of '{key: value}'.
with open("phonebook.txt", "w") as x:
json.dump(a, x)
Second, how do you delete from a file by using the users input.
I cannot see a way of changing this to delete from file instead of the dict 'a';
name = input("enter name of contact you want to delete: ")
if name in a:
del a[name]
EDIT. This is what ive done now but it doesnt do whats expected ( i also tried adding the .readlines where x is but it just gets errors.
def save(a):
with open("phonebook.txt", "w") as x:
for k in a:
json.dump(str(k)+" "+str(a[k]), x)
def load():
a = {}
with open("phonebook.txt", "r") as f:
for l in f:
a[l[0]] = l[1]
print (a)
def save works fine (as far as i can see anyway)
Also i have tried c = l.split() and a[c[0]] = c[1]. Just doesnt want to work !

First part
That's not JSON format. Do not use it if you need something else. Use plain text files, like
with open("phonebook.txt","w") as file :
for key, value in a.items() :
file.write(str(key)+" "+str(value))
Second part
It looks you loaded the file into dictionary a. In that case, you just need to write dictionary a back to the file after deleting. If you have not loaded the file into the dictionary yet, you can do it with:
a= {}
with open("phonebook.txt") as file :
for line in file.readlines() :
content= line.split()
a[content[0]]= content[1]

Related

How to open online reference from IPython?

Is there a way to have IPython open a browser pointed at the appropriate online reference?
Especially for numpy,scipy, matplotlib?
For example, the doc for numpy.linalg.cholesky is pretty hard to read in a terminal.
I don't think there is a direct way to make IPython or any shell to open up documentation online, because the primary job of shells is to let you interact with the things they are shells to.
We could however write a script to open a new tab on a browser with the documentation. Like so:
import webbrowser
docsList = {
"numpy" : lambda x: "https://docs.scipy.org/doc/numpy/reference/generated/" + x + ".html",
"scipy" : lambda x: "https://docs.scipy.org/doc/scipy/reference/generated/" + x + ".html",
"matplotlib" : lambda x: "https://matplotlib.org/api/" + x.split('.')[1] + "_api.html",
"default" : lambda x: "https://www.google.com/search?q=documentation+" + x
}
def online(method_name):
"""
Opens up the documentation for method_name on the default browser.
If the package doesn't match any entry in the dictionary, falls back to
Google.
Usage
-------
>>> lookUp.online("numpy.linalg.cholesky")
>>> lookUp.online("matplotlib.contour")
"""
try:
url = make_url(method_name)
except AttributeError:
print("Enter the method name as a string and try again")
return
webbrowser.open(url, new = 2)
return
def make_url(method_name):
package_name = method_name.split('.')[0]
try:
return docsList[package_name](method_name)
except KeyError:
return docsList["default"](method_name)
You could save the above as "lookUp.py" at a location that Python can find it in, and then import it whenever you need to use it.
Caveats:
This method takes strings as input, so if you call it on a function it'll throw an error.
>>> lookUp.online("numpy.linalg.cholesky")
Will work.
>>> lookUp.online(numpy.linalg.cholesky)
Will ask you to give it as a string.
So use autocomplete to get to the function and then wrap it in quotes to get it to work.

How to fix UnboundLocalError: local variable 'file_lines' referenced before assignment

So this is my function which is meant to read the lines of text from a file.
This is extracted from a larger program hence some of the comments may seem out of place. Anyways I need to use the functions text and file_lines in numerous other functions but even after declaring them as global I still get the UnboundLocalError: local variable 'file_lines' referenced before assignment error and I don't know what to do.
import sys
text = []
case = ''
file_lines = []
def read_file(file): # function to read a file and split it into lines
global text #sets variable text as a global variable for use in multiple locations
global case #handles case sensitivity.
try: #tests the statement after colon
open(file)
except:
print('oops no file found bearing that name')
else:
while file == '': #if the file name is blank print error, this prevents program from crashing
print ('error')
filename = input('enter a file and its extension ie file.ext\n>>')
with open(file) as f : #opens filewith name
text = f.read() #read all lines of program text.
print ("file successfully read")
print('TEXT SENSITIVITY TURNED ON !!!!!!')
text = text.split('\n')# breaks lines in file into list instead of using ".readlines"
# so that the program doesn't count blank lines
case == True
global file_lines
file_lines = text
a function that tries to use the read_lines variable would be
def find_words(words):
line_num = 0 # to count the line number
number_of_word = 0
if case == False:
words = words.lower()
file_lines = [file_lines.lower() for file_lines in text]
while "" in file_lines:
file_lines.remove('')
for lines in file_lines:
line_num += 1
if words in lines: #checks each for the words being looks for
print(line_num,"...", text[line_num-1])
number_of_word = 1
if number_of_word == 0: #to check if the word is located in the file
print('Words not found')
In your function find_words you forgot to specify that find_lines is global. Try
def find_words(words):
global file_lines
line_num = 0 # to count the line number
The function errors because file_lines is not defined within the scope of find_words otherwise.

f.open() issue resulting in Unbound error for f.close()

I don't quite have an answer but I'm narrowing it down. Somehow I'm mixing/confusing types, I believe, between what is provided by commands like 'os.path' and type str().
As I've made the assignment of the logfile(s) globally, even though I can print it in the function, when the variable is used in fout = open(... it's actually a null that's being referenced, i.e. open() doesn't like/can't use the type it finds.
The error:
UnboundLocalError: local variable 'fout' referenced before assignment
I am simply writing a log of dot files (left on USB drives by OSX) for deletion, but the try/except is now falling over. First the original version.
working code:
logFile = "/Users/dee/Desktop/dotFile_names.txt"
try:
fout = open(logFile, 'w')
for line in dotFile_names:
fout.write(line)
except IOError as e:
print ("Error : %s not found." % fout)
finally:
fout.close()
Attempting better practice, I sought to put the log file specs and path as variables so they can be modified if need be - I hope to make it cross platform workable. these variables are at the head of the program, i.e. not in main(), but I pass them in and print() statements have shown me they are successfully being referenced. i.e. I get this printed:
/Users/dee/Desktop/dotFile_names.txt
Despite this the error I get is:
UnboundLocalError: local variable 'fout' referenced before assignment -
error points at the "fout.close()" line
Error producing code
logFilespec = "dotFile_names.txt"
fullLogFileSpec = []
userDesktop = os.path.join(os.path.expanduser('~'), 'Desktop')
fullLogFilespec = os.path.join(userDesktop, logFilespec)
try:
print "opening " + fullLogFilespec
fout = open(fullLogFileSpec, 'w')
for line in dotFile_names:
print "..", # are we executing this line..?
fout.write(line)
except IOError as e:
print ("Error : %s not found." % fout)
finally:
print "\nclosing " + fullLogFilespec
fout.close()
I've found that if I modify this line by converting to a string
fout = open(fullLogFileSpec, 'w')
fout = open(str(fullLogFileSpec), 'w')
the error goes away, BUT NO file is created on the Desktop!
At the very least I guess that I am passing something unrecognisable to fout = open() but it is not being caught by the except. Then when I pass something that does seem to allow fout =open() to work it seems to be a ghost?
So I figure I am lost between a String and whatever kind of reference/pointer os.path.expanduser() gives me.
I'm sure it's insanely simple. Before adding the str() code I also checked all indentation, removing them all and adding back using the editor indent hotkeys, just in case that was affecting things somehow.
OK, it looks like I was wearing my dumb glasses, I think declaring
fullLogFileSpec = []
as a list instead of a string was my error.
Similar as it is, having re-written it without that list declaration this code is working fine:
logfile_directory = os.path.join(os.path.expanduser('~'),'Desktop')
log_bf_file_spec = 'ItemsFoundByFolder_' + Deez_1.current_datetime() + '.txt'
log_by_folder = os.path.join(logfile_directory, log_bf_file_spec)
the function later calls, with no error:
fout_by_folder = open(log_by_folder, 'w')

tkinter variable for drop down selection empty

I tried to program an app in tkinter that would load random lines from a file you select from a pull down menu and display the selected line in a text window.
It seems like the variable "var" in insert_text does not return the selected "option" but rather an "empty" string resulting in a the following error:
"File not found error" (FileNotFoundError: [Errno2] No such file or
directory: '').
Please help!
#!/usr/bin/env python
# Python 3
import tkinter
from tkinter import ttk
import random
class Application:
def __init__(self, root):
self.root = root
self.root.title('Random Stuff')
ttk.Frame(self.root, width=450, height=185).pack()
self.init_widgets()
var = tkinter.StringVar(root)
script = var.get()
choices = ['option1', 'option2', 'option3']
option = tkinter.OptionMenu(root, var, *choices)
option.pack(side='right', padx=10, pady=10)
def init_widgets(self):
ttk.Button(self.root, command=self.insert_txt, text='Button', width='10').place(x=10, y=10)
self.txt = tkinter.Text(self.root, width='45', height='5')
self.txt.place(x=10, y=50)
def insert_txt(self):
var = tkinter.StringVar(root)
name = var.get()
line = random.choice(open(str(name)).readlines())
self.txt.insert(tkinter.INSERT, line)
if __name__ == '__main__':
root = tkinter.Tk()
Application(root)
root.mainloop()
That's because you're just creating an empty StringVar that isn't modified later, thus returning an empty string.
The OptionMenu takes the command parameter that calls the specified method every time another option is selected. Now, you can call a method like this, replacing you insert_txt:
def __init__(self):
# ...
self.var = tkinter.StringVar()
self.options = tkinter.OptionMenu(root, var, *choices, command=self.option_selected)
# ...
def option_selected(self, event):
name = self.var.get()
# The stuff you already had
Additionally, you have to empty the Text widget, otherwise the previous text would stay. I think the Entry widget is better for that, too.

Groovy write to file (newline)

I created a small function that simply writes text to a file, but I am having issues making it write each piece of information to a new line. Can someone explain why it puts everything on the same line?
Here is my function:
public void writeToFile(def directory, def fileName, def extension, def infoList) {
File file = new File("$directory/$fileName$extension")
infoList.each {
file << ("${it}\n")
}
}
The simple code I'm testing it with is something like this:
def directory = 'C:/'
def folderName = 'testFolder'
def c
def txtFileInfo = []
String a = "Today is a new day"
String b = "Tomorrow is the future"
String d = "Yesterday is the past"
txtFileInfo << a
txtFileInfo << b
txtFileInfo << d
c = createFolder(directory, folderName) //this simply creates a folder to drop the txt file in
writeToFile(c, "garbage", ".txt", txtFileInfo)
The above creates a text file in that folder and the contents of the text file look like this:
Today is a new dayTomorrow is the futureYesterday is the past
As you can see, the text is all bunched together instead of separated on a new line per text. I assume it has something to do with how I am adding it into my list?
As #Steven points out, a better way would be:
public void writeToFile(def directory, def fileName, def extension, def infoList) {
new File("$directory/$fileName$extension").withWriter { out ->
infoList.each {
out.println it
}
}
}
As this handles the line separator for you, and handles closing the writer as well
(and doesn't open and close the file each time you write a line, which could be slow in your original version)
It looks to me, like you're working in windows in which case a new line character in not simply \n but rather \r\n
You can always get the correct new line character through System.getProperty("line.separator") for example.
I came across this question and inspired by other contributors. I need to append some content to a file once per line. Here is what I did.
class Doh {
def ln = System.getProperty('line.separator')
File file //assume it's initialized
void append(String content) {
file << "$content$ln"
}
}
Pretty neat I think :)
Might be cleaner to use PrintWriter and its method println.
Just make sure you close the writer when you're done
#Comment for ID:14.
It's for me rather easier to write:
out.append it
instead of
out.println it
println did on my machine only write the first file of the ArrayList, with append I get the whole List written into the file.
Kindly anyway for the quick-and-dirty-solution.