i was programming a notepad with tkinter, but when i tried to define "createNewFile" that create before creating the new file, ask you to save, but it give me an error. Expected an indented block (, line 32). Here's the code:
def createNewFile():
if len(textArea.get("1.0", END+"-1c")) > 0:
if messagebox.askyesno("Save?", "Do you wish to save the file?"):
saveFile()
else:
textArea.delete("1.0",END)
def saveFile():
file = filedialog.asksaveasfile(mode='w',defaultextension=".txt", filetypes=(("Text File",".txt"), ("All Files","*.*"),("HTML Files",".html .htm"),("CSS Files",".css")))
if file != None:
data = self.textArea.get('1.0', END+'-1c')
file.write(data)
file.close()
The line that follows the second if statement in the createNewFile() function (i.e., saveFile()) needs to be indented.
def createNewFile():
if len(textArea.get("1.0", END+"-1c")) > 0:
if messagebox.askyesno("Save?", "Do you wish to save the file?"):
saveFile()
else:
textArea.delete("1.0",END)
Related
I would need some of your expertise concerning GUI and more precisely PyQt4.
Context
I am currently designing a GUI with PyQt. It was previously done with wxPython, but I was kind of force to migrate to Qt due to internal issue.
At some point, I needed to display traditional RTF content, ie including hidden tags such as {\rtf1\ansi\ansicpg1252\deff0\deflang1036\deflangfe1036{\fonttbl{\f0\fswiss\fprq2\fcharset0 Calibri;}{\f1\froman\fprq2\fcharset2 Symbol;}}, \tx360 or \par and so on.
If I'm not mistaking, QTextEdit from PyQt can't "interpret" this RTF and will just display the whole string. But neither did wxPython and I had found a workaround provided by the wxPython community, which was to copy the string to windows clipboard and then paste it in the wanted text widget.
Thus, I had this piece of code:
class rtfClip():
def __init__(self):
self.CF_RTF = win32clipboard.RegisterClipboardFormat("Rich Text Format")
# Puts 'toPaste' on the clipboard
def setClipboard(self,toPaste):
cbOpened = False
# Wait for board availability, then do operations
while not cbOpened:
try:
win32clipboard.OpenClipboard(0)
cbOpened = True
win32clipboard.EmptyClipboard() # need to empty, or prev data will stay
win32clipboard.SetClipboardData(self.CF_RTF, toPaste)
win32clipboard.CloseClipboard()
except Exception, err:
# If access is denied, that means that the clipboard is in use.
# Keep trying until it's available.
if err[0] == 5: #Access Denied
pass
#print 'waiting on clipboard...'
# wait on clipboard because something else has it. we're waiting a
# random amount of time before we try again so we don't collide again
time.sleep( random.random()/50 )
elif err[0] == 1418: #doesn't have board open
pass
elif err[0] == 0: #open failure
pass
else:
print 'ERROR in Clipboard section of readcomments: %s' % err
pass
# Save the user's existing clipboard data, if possible. It is unable to save
# copied files, image data, etc; text, HTML, RTF, etc are preserved just fine
def saveClipboard(self):
cbOpened = False
while not cbOpened:
try:
win32clipboard.OpenClipboard(0)
cbOpened = True
self.cbSaved = {}
rval = win32clipboard.EnumClipboardFormats( 0 )
while rval != 0:
#print "Retrieving CB format %d" % rval
dat = win32clipboard.GetClipboardData( rval )
if rval == 15: #CF_HDROP
#this'll error, so just give up
self.cbSaved = {}
win32clipboard.EmptyClipboard()
break
else:
self.cbSaved[ rval ] = win32clipboard.GetClipboardData( rval )
rval = win32clipboard.EnumClipboardFormats( rval )
win32clipboard.CloseClipboard()
except Exception, err:
if err[0] == 5: #Access Denied
#print 'waiting on clipboard...'
time.sleep( random.random()/50 )
pass
elif err[0]== 6:
#print 'clipboard type error, aborting...'
win32clipboard.CloseClipboard()
break
elif err[0] == 1418: #doesn't have board open
cbOpened = False
elif err[0] == 0: #open failure
cbOpened = False
else:
print 'Error while saving clipboard: %s' % err
pass
# Restore the user's clipboard, if possible
def restoreClipboard(self):
cbOpened = False
# don't wait for the CB if we don't have to
if len(self.cbSaved) > 0:
#open clipboard
while not cbOpened:
try:
win32clipboard.OpenClipboard(0)
win32clipboard.EmptyClipboard()
cbOpened = True
except Exception, err:
if err[0] == 5: #Access Denied
#print 'waiting on clipboard...'
time.sleep( random.random()/50 )
pass
elif err[0] == 1418: #doesn't have board open
cbOpened = False
elif err[0] == 0: #open failure
cbOpened = False
else:
print 'Error with clipboard restoration: %s' % err
pass
#replace items
try:
for item in self.cbSaved:
data = self.cbSaved.get(item)
# windows appends NULL to most clipboard items, so strip off the NULL
if data[-1] == '\0':
data = data[:-1]
win32clipboard.SetClipboardData( item, data )
except Exception, err:
#print 'ERR: %s' % err
win32clipboard.EmptyClipboard()
try:
win32clipboard.CloseClipboard()
except:
pass
And then I just had to paste my RTF string in the associated widget:
rtf = copy_to_clipboard.rtfClip()
rtf.saveClipboard() # Save the current user's clipboard
rtf.setClipboard(my_rtf_string_full_of_rtf_tags) # Put our RTF on the clipboard
preview_dlg = preview_rtf_text(None)
preview_dlg.preview_rtf_ctrl.SetEditable(True)
preview_dlg.preview_rtf_ctrl.Paste() # Paste in into the textbox
rtf.restoreClipboard() # Restore the user's clipboard
preview_dlg.ShowModal()
preview_dlg.Destroy()
(preview_rtf_text being a class with only a TextCtrl named preview_rtf_ctrl)
Problem
My problem is that for any reason I can't manage to get this solution working with PyQt.
I have attempted designing a very similar solution with
rtf = copy_to_clipboard.rtfClip()
rtf.saveClipboard() # Save the current user's clipboard
rtf.setClipboard(rtf_content) # Put our RTF on the clipboard
#
rtf_preview_dlg = AEM_RTF_preview(self)
rtf_preview_dlg.rtf_preview_ctl.setReadOnly(False)
rtf_preview_dlg.rtf_preview_ctl.setAcceptRichText(True)
cursor = QtGui.QTextCursor(rtf_preview_dlg.rtf_preview_ctl.document())
cursor.setPosition(0)
rtf_preview_dlg.rtf_preview_ctl.setTextCursor(cursor)
rtf_preview_dlg.rtf_preview_ctl.paste()
rtf.restoreClipboard() # Restore the user's clipboard
rtf_preview_dlg.rtf_preview_ctl.setReadOnly(True)
rtf_preview_dlg.exec_()
But for any reason this won't work: nothing is pasted to the QTextEdit (rtf_preview_ctl).
I saw on some topics that PyQt had its own clipboard, but how would I make him "take" the content from the windows one? Is it even a solution?
Sorry for the very long question, I hope some of you may have an idea, since it would be an important feature of the GUI.
EDIT : There might be other solution for my need, my dream would just be to display formatted microsoft RTF content, one way or another.
I found a very old command line utility, unrtf. It outputs to STDOUT, so we need to process the output from there. It's been made for linux, but Windows binaries are available, even if the version I found is a bit older than the latest provided for Linux.
It requires to write a temporary file and might have some small issues with rtf conversion, but for simple cases seems to work fine enough.
In this case I automatically detect if there's some rtf content in the clipboard (so you can test it with along with your current program), but you can also paste raw rtf contents there to test it: you actually don't need the clipboard at all to make it work.
As far as I can understand it also supports tables and images, which are exported in external files (so you might have to test its behavior and possibly edit the html before actually applying it to the QTextEdit).
rtfTypes = set(['text/rtf', 'text/richtext', 'application/x-qt-windows-mime;value="Rich Text Format"'])
class PasteWidget(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
l = QtWidgets.QGridLayout()
self.setLayout(l)
self.input = QtWidgets.QTextEdit()
l.addWidget(self.input)
self.input.setAcceptRichText(False)
self.pasteBtn = QtWidgets.QPushButton('Paste')
l.addWidget(self.pasteBtn)
self.pasteBtn.clicked.connect(self.paste)
self.convertBtn = QtWidgets.QPushButton('Convert')
l.addWidget(self.convertBtn)
self.convertBtn.clicked.connect(self.convert)
self.output = QtWidgets.QTextEdit()
l.addWidget(self.output)
self.output.setReadOnly(True)
self.clipboard = QtWidgets.QApplication.clipboard()
self.clipboard.changed.connect(self.checkClipboard)
self.checkClipboard()
def checkClipboard(self, mode=QtGui.QClipboard.Clipboard):
if mode != QtGui.QClipboard.Clipboard:
return
self.pasteBtn.setEnabled(bool(set(self.clipboard.mimeData().formats()) & rtfTypes))
def paste(self):
mime = self.clipboard.mimeData()
for format in mime.formats():
if format in rtfTypes:
self.input.setPlainText(str(mime.data(format)))
def convert(self):
rtf = self.input.toPlainText()
if not rtf:
return
tempPath = QtCore.QDir.tempPath()
with open(os.path.join(tempPath, '_sourceRtf'), 'wb') as _input:
_input.write(rtf)
unrtf = QtCore.QProcess()
unrtf.readyReadStandardOutput.connect(lambda: self.output.setHtml(str(unrtf.readAllStandardOutput())))
unrtf.start('unrtf.exe', ['--html', os.path.join(tempPath, '_sourceRtf')])
Obviously the unrtf.exe has to be in the system path (or the path of the main script).
I have a class where all of our data is in, here I open a file by:
carIn= open("dataIn.txt","w")
carOut= open("dataUit.txt","w")
In another class I have a loop for the main program. I closed my file in the loop but it won't open again. If I close it outside the loop, the entire program crashes. This is my code:
while startScreen.getstopt() == False:
startScreen.start()
print("screen start")
screen = Screen(wereld.getIntersection())
startSimulatiion()
print("Simulatiion start:")
for x in Files.listIn:
Files.carIn.write(str(x) + "\n")
for x in Files.listOut:
Files.carOut.write(str(x) +"\n")
result= Resultaten()
Files.calculatedRatio= result.calculateRatio()
print(Files.calculatedRatio)
if screen.startScreen == True:
Files.carIn.write("\n")
Files.carIn.write("\n")
Files.carIn.write("\n")
Files.carOut.write("\n")
Files.carOut.write("\n")
Files.carOut.write("\n")
Files.carIn.close()
Files.carOut.close()
In my opinion, you shouldn't be holding open objects in class / instance variables to pass around. This will become messy and it's easy to forget to close explicitly.
Instead, I would hold the filenames in variables and pass them into functions which open and close files via with statements.
Here is an example:
Files.carIn = 'dataIn.txt'
Files.carOut = 'dataUit.txt'
with open(Files.carIn, 'w') as file_in, open(Files.carOut, 'w') as file_out:
while startScreen.getstopt() == False:
# do things with file_in & file_out
python 3.4.2, on Linux
I'm pretty new to this language but I'm coding this project. It started as a simple program that displayed a dictionary . Well I'm trying to expand on it based on tutorials that i am reading. I came to one about shelving and being able to preserve info in a save file in a format much like a dictionary. So far i have a program that takes input and updates the dictionary based on the input. It's very basic but it works on a simple level but naturally I would want to save what I entered. Following is the code so far.
the updateSaveP1() function is what is giving me trouble. Although not coded like this currently, i would ultimately like the function to take 2 arguments, one to name the key in the shelf file, and one to reference the target dictionary/ list etc. Currently its not even saving to the file.
the loadINV() function is a place holder and doent work as coded currently. i need to figure out the dbm problem first as i get the same dbmError with the load function too.
I originally just .opened the file. found documentation here at Stack that i should open it with either so that it creates the right file. I have tried both to no avail.
NOTICE**** this code will create an empty file on your system at the working directory of python named savedata.db
Much Thanks and appreciation for any help.
`import pygame, math, sys, os, pprint, shelve, dbm,
SAVE_LOCATION = os.path.join(os.getcwd() + '/savedata')
SAVE_FILE_LIST = os.listdir(os.getcwd())
SOURCE = os.path.dirname('inventory.py')
YES = ["y","Y"]
NO = ["n","N"]
playerStash = {"rope": 77,
"giant's toe" : 1,
"gold" : 420}
'''def loadINV():
fileTOload = dbm.open('savedata.db', 'w')
print('opened savedata file')
#for eachLine in fileTOload:
playerStash.update(str(fileTOload.read())
)
print('updated dict')
fileTOload.close()'''
def checkSavesFile():
while True:
if os.path.exists(SAVE_LOCATION):
print('Save file found')
break
elif os.path.exists(SAVE_LOCATION + '.db'):
print('.db Save file found')
loadINV()
break
else:
updateSaveP1()
print('New Save Created')
break
def updateSaveP1():
with dbm.open('savedata', 'c') as save:
save['player1'] = str(playerStash)
save.close()
#print(SAVE_LOCATION) #debugging - file name format verification
#pprint.pprint(SAVE_FILE_LIST) debugging will pretty print list of files
checkSavesFile() # runs the save file check
def askAboutInv(player):
while True:
print("What item would you like to add? \n\
(leave blank and press enter to quit)")
name = input() # Reads input and checks for duplicates or non entries
if name == '':
break # Stop loop
elif name in playerStash.keys():
# the check to see if input was in dictionary
dict_quant = int(playerStash.get(name, 0))
# "dict_quant" represents the value in dictionary as an integer
dict_item = str(playerStash.get(name, 0))
# "dict_item represents the value in dictionary as a string
addedItem = dict_quant + 1
#handles adding the value of the input
print("You have " + dict_item + " already, \n\
would you like to add more Y/N?")
# prints " You have "dictionary number" already"
answer = input()
# checks for input if you want to add more to inventory
if answer in YES: #checks to see if y or Y is entered
playerStash[name] = addedItem
# adds +1 to the quantity of "name" per the dict_quant variable
print("you have " + str(addedItem) + " now")
# prints " you have "new dictionary number" now"
if answer in NO: #checks to see if n or N was entered
print("Nothing added") #prints
break #ends loop
else: #if none others statements are true
if name not in playerStash.keys():
#if "name" / input is not in the dictionary
playerStash[name] = playerStash.setdefault(name, 1)
# add the item to the dictionary with a value of 1
print('Inventory updated.')
# prints
updateSaveP1()
def inventoryDisp(player):# displays dictionary pointing towards argument
print("Inventory")
item_total = 0
for eachOne in playerStash.items():
print(eachOne) # looks at and prints each item/ key in dictionary
for i, q in playerStash.items():
item_total = item_total + q #adds all the quantities / values up
print("Total number of items: " + str(item_total))
# prints total number of items in inventory
def updatedInv(player): #same as above just reads "updated inventory"
print("Updated Inventory")
item_total = 0
for eachOne in playerStash.items():
print(eachOne)
for i, q in playerStash.items():
item_total = item_total + q
print("Total number of items: " + str(item_total))
inventoryDisp(playerStash)
askAboutInv(playerStash)
updateSaveP1()
updatedInv(playerStash)`
Update*****
after changing this:
`def updateSaveP1():
with dbm.open('savedata', 'c') as save:
save['player1'] = str(playerStash)
save.close()`
to this:
`def updateSaveP1():
save = openShelf()
#save = shelve.Shelf(dbm.open('savedata', 'c')) #old code
save['player1'] = str(playerStash)
print(save['player1'])
save.close()`
it would seem that the dictionary does get saved. now the loadINV function is giving me trouble. This:
def loadINV():
fileTOload = dbm.open('savedata.db', 'w')
print('opened savedata file')
#for eachLine in fileTOload:
playerStash.update(str(fileTOload.read())
)
print('updated dict')
fileTOload.close()
is now this:
def loadINV():
file = openShelf()
print('opened savedata file')
playerStash.update(file['player1'])
print('updated dict')
fileTOload.close()
but the .update() method returns this error: which i can't seem to find any info.
Traceback (most recent call last):
File "/home/pi/inventoryShelve.py", line 58, in <module>
checkSavesFile() # runs the save file check
File "/home/pi/inventoryShelve.py", line 40, in checkSavesFile
loadINV()
File "/home/pi/inventoryShelve.py", line 25, in loadINV
playerStash.update(file['player1'])
ValueError: dictionary update sequence element #0 has length 1; 2 is required
Turned out I was saving (into the shelf) the data for the inventory dictionary as something other than a dict:
def updateSaveP1():
save = openShelf()
save['player1'] = str(playerStash)
#print(save['player1'])
save.close()
became
def updateSaveP1():
save = openShelf()
save['player1'] = dict(playerStash)
#print(save['player1'])
save.close()
So I wrote this code
spec = raw_input("Enter the specimen number: ")
naorimp = raw_input("Native or Implant (N/I)? ")
trial = raw_input("Trial number: ")
typana = raw_input("What do you want to analyze (contact area[CA]/contact pressure[CP])? ")
try :
if typana.lower() == "cp" :
naorimp = naorimp.upper()
TSfilnm = 'pressure'+spec+naorimp.upper()+trial+'.txt'
else :
naorimp = naorimp.upper()
TSfilnm = 'area'+spec+naorimp+trial+'.txt'
TSfile = open(TSfilnm, 'r')
myofilnm = 'accelerometer'+spec+naorim.upper()+trial+'.txt'
print myofilnm
myofile = open(myofilnm, 'r')
except :
print "File could not be found."
print "Please re-run the program."
exit()
print "OK"
I want to open a file based on user's input and several parameters (specimen no., native or implant, trial no., and type of analysis.) The file is already in the same folder as the python file code. But when I run the program I always end up with except statements (File could not be found. Please re-run the program). I have double-checked the real file name and the string inside the TSfilnm variable, and they are the same. However, the TSfile could not be executed.
P.S. The file name in my folder is: pressure3N1.txt, area3N1.txt, accelerometer3N1.txt
You are missing a p in the variable name in this line
myofilnm = 'accelerometer'+spec+naorim.upper()+trial+'.txt'
should be
myofilnm = 'accelerometer'+spec+naorimp.upper()+trial+'.txt'
Also don't use 'except' alone during development, it will only hide errors like in this case. It's better to do something like.
import sys
try:
#Your_code_here
except:
print sys.exc_info()[1]
#Any other code you wanna run
I have a python script that calls a system program and reads the output from a file out.txt, acts on that output, and loops. However, it doesn't work, and a close investigation showed that the python script just opens out.txt once and then keeps on reading from that old copy. How can I make the python script reread the file on each iteration? I saw a similar question here on SO but it was about a python script running alongside a program, not calling it, and the solution doesn't work. I tried closing the file before looping back but it didn't do anything.
EDIT:
I already tried closing and opening, it didn't work. Here's the code:
import subprocess, os, sys
filename = sys.argv[1]
file = open(filename,'r')
foo = open('foo','w')
foo.write(file.read().rstrip())
foo = open('foo','a')
crap = open(os.devnull,'wb')
numSolutions = 0
while True:
subprocess.call(["minisat", "foo", "out"], stdout=crap,stderr=crap)
out = open('out','r')
if out.readline().rstrip() == "SAT":
numSolutions += 1
clause = out.readline().rstrip()
clause = clause.split(" ")
print clause
clause = map(int,clause)
clause = map(lambda x: -x,clause)
output = ' '.join(map(lambda x: str(x),clause))
print output
foo.write('\n'+output)
out.close()
else:
break
print "There are ", numSolutions, " solutions."
You need to flush foo so that the external program can see its latest changes. When you write to a file, the data is buffered in the local process and sent to the system in larger blocks. This is done because updating the system file is relatively expensive. In your case, you need to force a flush of the data so that minisat can see it.
foo.write('\n'+output)
foo.flush()
I rewrote it to hopefully be a bit easier to understand:
import os
from shutil import copyfile
import subprocess
import sys
TEMP_CNF = "tmp.in"
TEMP_SOL = "tmp.out"
NULL = open(os.devnull, "wb")
def all_solutions(cnf_fname):
"""
Given a file containing a set of constraints,
generate all possible solutions.
"""
# make a copy of original input file
copyfile(cnf_fname, TEMP_CNF)
while True:
# run minisat to solve the constraint problem
subprocess.call(["minisat", TEMP_CNF, TEMP_SOL], stdout=NULL,stderr=NULL)
# look at the result
with open(TEMP_SOL) as result:
line = next(result)
if line.startswith("SAT"):
# Success - return solution
line = next(result)
solution = [int(i) for i in line.split()]
yield solution
else:
# Failure - no more solutions possible
break
# disqualify found solution
with open(TEMP_CNF, "a") as constraints:
new_constraint = " ".join(str(-i) for i in sol)
constraints.write("\n")
constraints.write(new_constraint)
def main(cnf_fname):
"""
Given a file containing a set of constraints,
count the possible solutions.
"""
count = sum(1 for i in all_solutions(cnf_fname))
print("There are {} solutions.".format(count))
if __name__=="__main__":
if len(sys.argv) == 2:
main(sys.argv[1])
else:
print("Usage: {} cnf.in".format(sys.argv[0]))
You take your file_var and end the loop with file_var.close().
for ... :
ga_file = open(out.txt, 'r')
... do stuff
ga_file.close()
Demo of an implementation below (as simple as possible, this is all of the Jython code needed)...
__author__ = ''
import time
var = 'false'
while var == 'false':
out = open('out.txt', 'r')
content = out.read()
time.sleep(3)
print content
out.close()
generates this output:
2015-01-09, 'stuff added'
2015-01-09, 'stuff added' # <-- this is when i just saved my update
2015-01-10, 'stuff added again :)' # <-- my new output from file reads
I strongly recommend reading the error messages. They hold quite a lot of information.
I think the full file name should be written for debug purposes.