I am trying to use PYQT5 file picker, but there is something I am missing. I'm having two problems. the first is when the file dialog box opens and I choose a file. the whole program crashed and I get AttributeError: 'list' object has no attribute 'seek' and QWaitCondition: Destroyed while threads are still waiting that show in the terminal. The second is when I hit cancel on the file dialog the whole program crashes and it says nboundLocalError: local variable 'newdata' referenced before assignment and QWaitCondition: Destroyed while threads are still waiting. What I would like is to be able to have the dialog pop up and choose the file and then and then have the contents of that file be loaded into that variable. I'm not sure what is going wrong. I have posted my current code below. Any advice or help is greatly appreciated.
def open(self):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
try:
fileToOpen = QFileDialog.getOpenFileNames(self,"Open File", "","All Files (*);;Python Files (*.py)", options=options)
except:
pass
pdb.set_trace()
if fileToOpen:
with ZipFile(fileToOpen, 'r') as myzip:
json_data_read = myzip.read('digest.json')
newdata = json.loads(json_data_read)
Functions.Loads = newdata[1]
getOpenFilename returns a tuple. You want the second return value so call it like
fileToOpen, _ = getOpenFilename(...)
It's because pyqt5 calls getOpenFilenameAndFilter: http://pyqt.sourceforge.net/Docs/PyQt5/pyqt4_differences.html#qfiledialog
The second problem is because you don't init newData if there is no filename.
Related
I need to make a download button for more than one file. Streamlit's download button doesn't let you download more than one file. I tried to make a few buttons, but the rest just disappear when I click the first one. Is there any way to download two or more files in Streamlit?
I tried this solution from Github, this is what the code looks like:
if st.button("Rozpocznij proces"):
raport2 = Raport.raport_naj_10(gender,year,week,engine)
raportM = raport2[0]
raportO = raport2[1]
st.dataframe(raportM)
st.dataframe(raportO)
zipObj = ZipFile("sample.zip", "w")
# Add multiple files to the zip
zipObj.write("raportM")
zipObj.write("raportO")
# close the Zip File
zipObj.close()
ZipfileDotZip = "sample.zip"
with open(ZipfileDotZip, "rb") as f:
bytes = f.read()
b64 = base64.b64encode(bytes).decode()
href = f"<a href=\"data:file/zip;base64,{b64}\" download='{ZipfileDotZip}.zip'>\
Click last model weights\
</a>"
st.sidebar.markdown(href, unsafe_allow_html=True)
But I get this error:
FileNotFoundError: [WinError 2] Nie można odnaleźć określonego pliku: 'raportM'
It says that can't find the file named "raportM".
You are having those errors because the code is written with an assumption that you already have the files stored and you want to generate a zip file for them. zipObj.write("raportM") is looking for the file named "raportM" and there isn't any, because in your case you do not have these files stored. I can see that you are passing variable names as files and that is not going to work.
What you will have to do is to save those variable names as CSV files in your local machine before doing the above operations.
In this case lets modify your code. But before that we need to initialize a session state for the button st.button("Rozpocznij proces") because streamlit button have no callbacks.
processbtn = st.button("Rozpocznij proces")
# Initialized session states
if "processbtn_state" not in st.session_state:
st.session_state.processbtn_state = False
if processbtn or st.session_state.processbtn_state:
st.session_state.processbtn_state = True
raport2 = Raport.raport_naj_10(gender,year,week,engine)
raportM = raport2[0]
raportO = raport2[1]
st.dataframe(raportM)
st.dataframe(raportO)
# Save files
raportM.to_csv('raportM.csv') # You can specify a directory where you want
raportO.to_csv('raportO.csv') # these files to be stored
# Create a zip folder
zipObj = ZipFile("sample.zip", "w")
# Add multiple files to the zip
zipObj.write("raportM.csv")
zipObj.write("raportO.csv")
# close the Zip File
zipObj.close()
ZipfileDotZip = "sample.zip"
with open(ZipfileDotZip, "rb") as f:
bytes = f.read()
b64 = base64.b64encode(bytes).decode()
href = f"<a href=\"data:file/zip;base64,{b64}\" download='{ZipfileDotZip}.zip'>\
Click last model weights\
</a>"
st.sidebar.markdown(href, unsafe_allow_html=True)
At this moment, when you pay close attention to your directories you will find 'raportM.csv' and 'raportO.csv' files. You can pass a condition to the download button so that whenever a download is made the files should be deleted in case you don't want to keep them.
Note: You may encounter fileNotFound Error but does not mean that it won't work, you will just need to know where you are saving the files.
I'm a new user of Qt and I'm trying to fix a persistent crashing issue that happens in my 'open file' dialogue. Whenever I open a file dialogue to select a file and decide to hit cancel instead, it causes python to stop working.
This is what the code looks like right now:
# get save file
savefile, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open file", "", "Files (*.mat)")
self.matlocation = savefile
I've tried using:
savefile, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open file", "", "Files (*.mat)")
if(!fileName.isEmpty()&& !fileName.isNull()){
self.matlocation = savefile
}
but this is still causing crashes. Am I missing something?
Thanks in advance.
Edit
It's part of a larger function:
So it's part of a function from a larger .py. The function as it stands starts by loading in a mat file:
def loadmat(self):
from PyQt5 import QtWidgets
import functions.plotting as plot
# get save file
savefile, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open file", "", "Files (*.mat)")
self.matlocation = savefile
# set mat location in GUI box
self.gui.samplelocBox.setPlainText(self.matlocation)
I don't know why this started happening recently. I have a function that opens a new text file, writes a url to it, then closes it, but it is not made immediately after the f.close() is executed. The problem is that a function after it open_url() needs to read from that text file a url, but since nothing is there, my program errors out.
Ironically, after my program errors out and I stop it, the url.txt file is made haha. Anyone know why this is happening with the python .write() action? Is there another way to create a text file and write a line of text to that text file faster?
#staticmethod
def write_url():
if not path.exists('url.txt'):
url = UrlObj().url
print(url)
with open('url.txt', 'w') as f:
f.write(url)
f.close
else:
pass
#staticmethod
def open_url():
x = open('url.txt', 'r')
y = x.read()
return y
def main():
scraper = Job()
scraper.write_url()
url = scraper.open_url()
results = scraper.load_craigslist_url(url)
scraper.kill()
dictionary_of_listings = scraper.organizeResults(results)
scraper.to_csv(dictionary_of_listings)
if __name__ == '__main__':
main()
scheduler = BlockingScheduler()
scheduler.add_job(main, 'interval', hours=1)
scheduler.start()
There is another class called url that prompts the user to add attributes to a bare url for seleenium to use. UrlObj().url gives you the url to write which is used to write to the new text file. If the url.txt file already exists, then pass and go to open_url()and get the url from the url.txt file to pass to the url variable which is used to start the scraping.
Just found a work around. If the file does not exist then return the url to be fed directly to load_craigslist_url. If the text file exists then just read from the text file.
I want to make a python script that opens a text file that the user can update before continuing (for configurations) and then continue the script once the text editor closes. Is there something in python that will allow me to do this?
on windows using notepad:
import os
cf = "config.txt" # or full path if you like
if not os.path.exists(cf):
f = open(cf,"w"); f.close() # create to avoid notepad message
os.system("notepad "+cf) # call waits until user closes the file
# now the file has been edited by the user
I'm trying to make a savefile dialog in tkinter. I need to save the file name to use later. However, I do not want the filedialog to accept selecting an already existing file name.
So far I only have this:
from tkinter import filedialog
my_file = filedialog.asksaveasfilename(defaultextension = ".myfile",
filetypes = [("MY SUPER FILE", ".myfile"),
("All files", ".*")])
One possibility would be to get the file name, check if it exists (using os.path.isfile) and ask again the user for new name if there is already a file with the same name. However, the tkinter filedialog asks the user "file already exists. do you want to overwrite?". So it seems confusing if later I tell the user that I do not accept the filename choice. Is there a way to force the tkinter filedialog to not ask the user about the overwriting?
Edit: Based on the suggestions in the answers, I tried to make my own save file dialog.
I basically only added a warning to the tkinter save dialog:
class MySaveFileDialog(filedialog.FileDialog):
""" File save dialog that does not allow overwriting of existing file"""
def ok_command(self):
file = self.get_selection()
if os.path.exists(file):
if os.path.isdir(file):
self.master.bell()
return
messagebox.showarning("The current file name already exists. Please give another name to save your file.")
else:
head, tail = os.path.split(file)
if not os.path.isdir(head):
self.master.bell()
return
self.quit(file)
So, it looks pretty simple. Then I thought: I need to create my own asksaveasfilename function.
I went to check the source:
def asksaveasfilename(**options):
"Ask for a filename to save as"
return SaveAs(**options).show()
Humm.. I need to see what is SaveAs doing.
class SaveAs(_Dialog):
"Ask for a filename to save as"
command = "tk_getSaveFile"
Aaannddd... i'm lost. I don't understand how this pieces fit together. 'SaveAs' just has the command tk_getSaveFile. How is the SaveFileDialog being used here? And how can I make my own myasksaveasfilename function?
There is no such option. If you want to get rid of the security question, then you'll have to write your own file dialog.
If you look at filedialog.py, you'll see that the dialog is implemented in Python. So all you have to do is to extend the class SaveFileDialog and override the method ok_command() with one that doesn't allow to select an existing file name.
You can use most of the existing code and just change a few texts to achieve your goal.
I haven't tested it but this code should work:
def ok_command(self):
file = self.get_selection()
if os.path.exists(file):
if os.path.isdir(file):
self.master.bell()
return
d = Dialog(self.top,
title="Overwrite Existing File",
text="You can't overwrite an existing file %r. Please select a new name." % (file,),
bitmap='error',
default=0,
strings=("OK",))
return
else:
head, tail = os.path.split(file)
if not os.path.isdir(head):
self.master.bell()
return
self.quit(file)
An answer to a slightly adjacent topic, but this was the closest existing question on SO so assume others may end up here when faced with the same problem, and I got my answer from above information.
If you are looking to select a tk.filedialog.asksaveasfile, but without overwriting an existing file (ie append to it), and wanting to avoid users being faced with the 'Do you want to overwrite?' popup, one can select the append mode, and turn off the overwrite popup.
outfilename = tk.filedialog.asksaveasfile(title = 'Save processing output CSV',
initialdir = output_directory,
defaultextension = '.csv',
mode = 'a',
confirmoverwrite = False,
filetypes = (('csv File', '.csv'),)
)
To complete what Aaron said, here is the current code of ok_command:
def ok_command(self):
file = self.get_selection()
if os.path.exists(file):
if os.path.isdir(file):
self.master.bell()
return
d = Dialog(self.top,
title="Overwrite Existing File Question",
text="Overwrite existing file %r?" % (file,),
bitmap='questhead',
default=1,
strings=("Yes", "Cancel"))
if d.num != 0:
return
else:
head, tail = os.path.split(file)
if not os.path.isdir(head):
self.master.bell()
return
self.quit(file)
You can achieve this using tkFileDialog.asksaveasfilename(confirmoverwrite=False)
Here is a mock up:
import tkFileDialog
import tkMessageBox as mbox
class Example():
proceed = False
while proceed == False:
dlg = tkFileDialog.asksaveasfilename(confirmoverwrite=False)
fname = dlg
if fname != '':
try:
f = open(fname, "r")
f.close()
mbox.showerror("Error","File exists - Choose another file name")
except:
mbox.showinfo("Info","File does not exist - Continue")
proceed = True
else:
break
print("Finished")