France
Asked — Edited
Resolved Resolved by ptp!

I Need Help For A Python Script (Conversion Of An Old EZ Script)

Hi,

I try to convert an old EZ scripts into a python scripts It is a script that reads a number from a txt file, makes a calculation, then rewrite the file with the new value.

The following EZ scripts works fine:


# Close the text file to make it accessible
FileReadClose("C:\Users\FredWin\Documents\ARC\Scripts\Calc.txt")

# Obtain a number from the text files and use it as variable
$calc = FileReadAll("C:\Users\FredWin\Documents\ARC\Scripts\Calc.txt")

# Show the number in the debug window<br />Print("old value:")
Print($calc)

# Calculation
$calc = $calc + 1
Print("---")
Print("new value:")
Print($calc)
FileDelete("C:\Users\FredWin\Documents\ARC\Scripts\Calc.txt")
FileWrite("C:\Users\FredWin\Documents\ARC\Scripts\Calc.txt", $calc)

But the following python script does not:


# Close the text file to make it accessible
File.ReadClose("C:\Users\FredWin\Documents\ARC\Scripts\Calc2.txt")

# Obtain a number from the text files and use it as variable
setVar("$calc2", File.ReadAllText("C:\Users\FredWin\Documents\ARC\Scripts\Calc2.txt") )
calc2 = (getVar( "$calc2" ))

# Show the number in the debug window
print("old value")
print(calc2, type(calc2))

# Calculation
calc2 = ( calc2 + 1)
print("---")
print("new value")
print(calc2, type(calc2))
File.Delete("C:\Users\FredWin\Documents\ARC\Scripts\Calc2.txt")
File.Append("C:\Users\FredWin\Documents\ARC\Scripts\Calc2.txt", calc2)

The problem seems to be with the "File.Append" function. Instead of putting a number for the new calc2 value in the txt file, it writes a special character. So after that, calc2 is considered as a string, and the scripts cannot make the calculation anymore.

Any idea ? Thanks


Related Hardware EZ-B v4
Related Control Script

ARC Pro

Upgrade to ARC Pro

Stay on the cutting edge of robotics with ARC Pro, guaranteeing that your robot is always ahead of the game.

#2   — Edited
path = ("C:\Users\FredWin\Documents\ARC\Scripts\Calc2.txt")
def calc():
    with open(path,'r+') as file:
        calc2 = int(file.read())
        print('old value')
        print(calc2)
        calc2 = (calc2 + 1)
        print('new value')
        print(calc2)
        file.truncate(0)  # to remove content in your file
        file.seek(0)
        file.write(str(calc2))

calc()

Hey there, I hope I understood correctly what you are trying to achieve...this code should work!:D

PRO
USA
#3  

Short mode:

@Fredbec and others: You are mixing different environments, so is important to understand each and the limitations.

@DJ: There is a bug

Next I'll breakdown in multiple posts.

PRO
USA
#4  

Python World: There is Python 2 and Python 3, and they are not the same there are significant changes, Python 2 is deprecated.

ARC Python support is build on top of IronPython https://ironpython.net/ I've crossed paths a few years ago and we gave up due to lack of support, IronPython is on life support. Microsoft gave up, the main architect left to google and is being supported by volunteers.

IronPython is (Python 2).

The reason why Python is growing is due to the use on scientific, robotic and ITOps areas, also there are a lot of good libraries to do impressive stuff scipy https://www.scipy.org/ is one of them.

There is another player CPython: https://en.wikipedia.org/wiki/CPython, allows calling native methods from C, is used also to compile Python to C. That is the reason why some ROS scripts work well in embedded computers, the Python libraries are calling native code (c++).

When Microsoft released the IronPython, the community look to integrate different libraries with IronPython, but, there is a problem IronPython works on top of .NET so is managed not native code.

Anything with components written in C (for example NumPy, which is a component of SciPy) will not work on IronPython as the external language interface works differently. Any C language component will probably not work unless it has been explicitly ported to work with IronPython.

So basically all the python super powerful libraries are not available to IronPython.

Is important to understand there are a few different types in Python: bytes, bytearray, list and tuples, they look the same but they are different.

Python2 script:

def PrintType(arg):
   print "{} {}".format(type(arg), arg)

str1 = 'this is a string'
PrintType(str1)

bytes1 = bytes(str1)
PrintType(bytes1)

bytearray1 = bytearray(str1)
PrintType(bytearray1)

list1 = [1,2,3,4,5]
PrintType(list1)

tuple1 = (1,2,3,4,5)
PrintType(tuple1)

Python 2 execution:

User-inserted image

ARC (IronPython):

User-inserted image

One of differences between Python 2 and Python 3 is the bytes type.

In Pyton2 bytes type is an alias to str type.

But that is not true in IronPython, bytes is not an alias. There are other differences between Python 2 and IronPython, and sometimes they can be relevant when using Python 2 code.

To summarize: Use Python 2 code Some Python 2 code may not work as expected on top of IronPython (ARC)

PRO
USA
#5   — Edited

EZ-Script: EZ-Script has a few of limitations, and is easy to understand why DJ is pushing and motivating people to move to Javascript (Interpreted), Python2 (.NET Managed = .NET C# code).

One of the issues with EZ-Script is the lack of data types, initially everything was handled as string, and converted on demand (when needed) to integers (32 bits), later DJ changed the conversion to big ints (64 bits).

So basically when you set a variable in ARC, there is no type, so if you send a typed value from Javascript, Pyhon, plugin (C#)  to EZ-Script and you try to get the value back you will lose the original type.

One example:

User-inserted image

So if you send a string to ARC, and if that is string is similar to number ARC will return a float. So is important to understand you need to convert back to the original type and or validate if the value is not changed in between your calls. In my example I sent a string "10" and i got back a float, the script will fail if i use the value to concat with another string.

import datetime

def printType(arg, org=''):
  print "{} {} {}".format(org, arg, type(arg))

print "---"

var1=10
printType(var1)
setVar("$arc1", var1)
printType(getVar("$arc1"), 'arc=>')
print "---"

var1=10.1
printType(var1)
setVar("$arc1", var1)
printType(getVar("$arc1"), 'arc=>')
print "---"

var1="10"
printType(var1)
setVar("$arc1", var1)
printType(getVar("$arc1"), 'arc=>')
print "---"

var1 = datetime.datetime.now()
printType(var1)
setVar("$arc1", var1)
printType(getVar("$arc1"), 'arc=>')
print "---"

To summarize: Keep your calculations in one side (Python), and if you exchange values with EZ-Script pay attention to the types, don't assume the value data  type is the same, validate and use conversion functions: str(x), int(x), float(x)  

PRO
USA
#6  

@DJ: There is a bug you can't call:

File.Append(filename, byteArray) 

from python. I believe your implementation does not take in consideration the different Python types: bytes, bytearray, list, tuple

Python script:

def PrintType(arg):
   print 'pythonType={} value={}'.format(type(arg), arg)


str1 = 'this is a string'
PrintType(str1)

bytes1 = bytes(str1)
PrintType(bytes1)

byteArray1 = bytearray(str1)
PrintType(byteArray1)

list1=[1, 2, 3, 4, 5]
PrintType(list1)

tuple1 = (1, 2, 3, 4, 5)
PrintType(tuple1)

filename="c:\temp\test1.txt"
File.ReadClose(filename);
File.Append(filename, byteArray1)

User-inserted image

None of the "array types" will work with File.Append

I did a small implementation here: https://github.com/ppedro74/Utils/blob/master/IronPythonTests/IronPythonTests.Common/PythonEngine.cs

User-inserted image

you will need different method signatures on File.Append to support the different Python types.

PRO
USA
#7  

@Fredebec:

I fixed your Python script:

fileName="c:\\temp\\calc.txt"
File.ReadClose(fileName)

str1=File.ReadAllText(fileName)
int1=int(str1)
int1=int1+1

setVar("$value1", int1)

str1 = str(int1)
File.Delete(fileName)
File.AppendString(fileName, str1)

#get value from ARC
var1=getVar("$value1")
int1=int(var1)
int1=int1+1

str1 = str(int1)
File.Delete(fileName)
File.AppendString(fileName, str1)

I prefixed the variables with type to be clear the data type being used.

PRO
Synthiam
#8   — Edited

Right on - i fixed the file append and other byte array references for the next beta channel release

England
#9  

Also note the filename from PTP's solution. You cannot use a single backslash "" as this is used to denote a special character. Most python variations will allow you to use the forward slash "/" instead without any problems ie

'c:/folder/subfolder/filename'

Another option is :-

import os myfile = os.path.normpath('c:/folder/subfolder/filename') open(myfile)

I'll have to test how these work with ARC python.

skidroe

England
#10   — Edited

Using the forward slash it will work on Windows and Linux. Tested with ARC and this works fine :-

myfile = "C:/temp/Calc.txt"

f = open(myfile) val = int(f.read()) f.close()

print "Old Value is ", val val = val + 1 setVar("$calc", val)

print "New Value is ", val

f = open(myfile,"w") f.write(str(val)) f.close()

#11  

Thank you all for your help and all the information. Some is a little beyond my actual knowledge, but I will learn... :-)

I have to admit I am a little lost between what is specific to Python and what is related to ARC. For example, to open and write into a file, I don't know if I should use "File.Read..." and "File.Append..." or some command suggested by @skidroe ("open(myfile)", "...write",...) and what's the difference...

PRO
USA
#12  

Quote:

I have to admit I am a little lost between what is specific to Python and what is related to ARC.
EZ-Script does not support object model, so ARC created specific objects to group similar functionalities:

JS:

User-inserted image

Python

User-inserted image

So you can see there are consistency between languages and features.

Returning to your Python code: File.* is a ARC object not a native Python2 object.

PRO
USA
#13   — Edited

@Mickey script post #2:

path = ("C:\Users\FredWin\Documents\ARC\Scripts\Calc2.txt")
def calc():
    with open(path,'r+') as file:
        calc2 = int(file.read())
        print('old value')
        print(calc2)
        calc2 = (calc2 + 1)
        print('new value')
        print(calc2)
        file.truncate(0)  # to remove content in your file
        file.seek(0)
        file.write(str(calc2))

calc()

or @skidroe script post #10

myfile = "C:/temp/Calc.txt"

f = open(myfile)
val = int(f.read())
f.close()

print "Old Value is ", val
val = val + 1
setVar("$calc", val)

print "New Value is ", val

f = open(myfile,"w")
f.write(str(val))
f.close()

They use Python 2, and btw Python3 file APIs are slightly different, but, you need to stick with Python 2. The exception is the ARC: setVar function.

ARC Javascript uses a .NET JS interpreter https://github.com/sebastienros/jint and has Full support for ECMAScript 5.1: http://www.ecma-international.org/ecma-262/5.1/ The component only supports the language so File access requires the ARC File object.

ARC Python uses IronPython a .net dynamic language, and supports Python 2 standard lib which includes different modules like file access, networking, serial etc. So if you want to access the file system, or even the .NET classes you can do it from Python, you don't need to use File ARC object.

other objects like: Audio, ADC, Ping etc,  are specific to ARC features. IronPython detailed documentation: https://ironpython-test.readthedocs.io/en/latest/contents.html

#14  

@ptp, thanks a lot for your explanations. It is really helpful !

I am now going to play a little bit with everything I have learned in this thread...

#15  

Hey guys, I also learned a lot here...I did not really pay attention how Python is being implemented within ARC, and just used Python 3 out of habit! Ups!!:D