[Python] How to save/reload regions using a file

Asked by SkaiCloud

****** solution with Python marshal

See comment #7

---------------------------------------------------

Hello I'm running into something I can't figure out. This might be a python question than sikuli but since sikuli functions is involve I should ask here. I trying to write several region to a file called region.txt

3 Region Variables:
r1=Region(252,120,150,25)
r2=Region(252,140,150,25)
r3=Region(252,160,150,25)

#Save Function call by swing button
def save(event):
filename="C://region.txt"
regionfile=open(filename,"w")
regionfile.write("r1="+str(r1)+"\n"
regionfile.write("r2="+str(r2)+"\n"
regionfile.write("r3="+str(r3)+"\n"
regionfile.close()

I open the file and it produce these:
r1=Region[252,120 150x25]@Screen(0) E:Y, T:3.0
r2=Region[252,140 150x25]@Screen(0) E:Y, T:3.0
r3=Region[252,160 150x25]@Screen(0) E:Y, T:3.0
instead of these:
r1=Region(252,120,150,25)
r2=Region(252,140,150,25)
r3=Region(252,160,150,25)
I tried using pickle dump but it cannot coarse to int and obviously converting it to strings won't work either. Any suggestion? My only other option might have to create a separate function to open the file and delete or change those unwanted extra characters. I do need to read from this file too just fyi

Question information

Language:
English Edit question
Status:
Answered
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:

This question was reopened

Revision history for this message
RaiMan (raimund-hocke) said :
#1

str() or repr() on an object produces a string representation of the object, that is a return value of a standard built-in method, that can be overwritten by the class designer.

In this case, they have Sikuli developers have decided to do it this way ;-)

do this when writing to file:
regionfile.write("r1="+str(r1).split('@')[0]+"\n")

Revision history for this message
RaiMan (raimund-hocke) said :
#2

sorry, you want to have ( instead of [:
regionfile.write("r1="+str(r1).split('@')[0].replace('[',')').replace(']',')')+"\n")

and yes, it is a basic Python question ;-) but never mind ::-))

Revision history for this message
SkaiCloud (flypilot43) said :
#3

Thnx Raiman! That solves it, I would have never figured that out.

Revision history for this message
SkaiCloud (flypilot43) said :
#4

using the method stated by Raiman will output the region variable as a string so you would have to use the exec to execute the string.

this is one region variable:
regionfile.write("r1="+str(r1).split('@')[0].replace('Region','"Region').replace('[','(').replace(']',')"').replace(' ',',').replace('x',',')+"\n")

to read that line and convert it to a variable I use this method:
import imp
data = imp.load_source('data', '', regionfile)
r1Str="r1="+data.r1
exec(r1Str)

I'm sure their are more elite ways to do it but this is the simplist I found.Just wanted to share how to read a file import the string from the file and convert it to variables so you can use it in your program.

Revision history for this message
SkaiCloud (flypilot43) said :
#5

Hello Raiman,
I'm stump on this one agian apparently exec(r1Str) won't because when I print the r1Str it will only give me a string of the region.
like r1=region(252,120,150,25). I now like to take that strong and use it as a sikuli variables. Any idea how to do this. I look everywhere and most approach I tried seems to fail me.

Revision history for this message
RaiMan (raimund-hocke) said :
#6

I do not really understand.

supposing r1str1 contains the string:
r1=region(252,120,150,25)

then saying
exec(r1str1)

should result in r1 being a "real" Region object.

so:
r1str1 = "r1=region(252,120,150,25)"
exec(r1str1)
print r1

should print:
Region[252,120 150x25]@Screen(0) E:Y, T:3.0

so you have your variable r1 being a region in your current context.

Revision history for this message
RaiMan (raimund-hocke) said :
#7

This is a basic setup with Python marshal, that uses a dictionary, to store the Region position/size.
This should run as is in Sikuli IDE.

import marshal
class dictRegions:
    def __init__(self):
        self.d = {}
    def getRegs(self): # returns the dict
        return self.d
    def setRegs(self, d): # sets the dict based on the given dict
        self.d = d.copy()
    def getReg(self, r): # returns a region
        rx = self.d.get(r, None)
        if not rx: return None
        return Region(rx[0], rx[1], rx[2], rx[3])
    def addReg(self, n, r): # adds a region to dict
        self.d[n] = (r.x, r.y, r.w, r.h)
    def saveRegs(self, f): # saves the dict to file
        save = file(f, "wb")
        marshal.dump(self.d, save)
        save.close()
    def loadRegs(self, f): # reloads the dict from file
        save = file(f, "rb")
        self.d = marshal.load(save)
        save.close()

# ****** usage as examples
print "\n**** step 1: original"
d = dictRegions()
d.addReg("r1", Region(100,200,300,400))
reg1 = d.getReg("r1")
print "reg1=", reg1
reg2 = reg1.right(200)
d.addReg("r2", reg2)
d.saveRegs("/Users/rhocke/saveregs.txt")
print "saved dictRegions=", d.getRegs()

print "\n**** step 2: modified"
dnew = {"r1":(101, 201, 301, 401)}
d.setRegs(dnew)
print "r1=", d.getReg("r1")
print "modified dictRegions=", d.getRegs()

print "\n**** step 3: reloaded"
d.loadRegs("/Users/rhocke/saveregs.txt")
reg1 = d.getReg("r1")
print "reg1=", reg1
print "reloaded dictRegions=", d.getRegs()

Can you help with this problem?

Provide an answer of your own, or ask SkaiCloud for more information if necessary.

To post a message you must log in.