I'm currently trying to loop over roughly 9000 .txt files in python to extract data and add them to a joined pandas data frame. The .txt data is stored in bytes, so in order to access it I was told to use a decoder. Because I'm interested in preserving special characters, I would like to use the UTF-8 decoder, but I'm getting the following error when trying to do so:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 3131: invalid start byte
For some reason, the code works just fine when using a 'ISO-8859-1' decoder, but this obviously messes up all special characters. Does anyone know how to fix this? I'm pasting my code below! Also, the decoding works for the first ~1600 .txt files in my dataset, but for the rest it doesn't.
decode_counter = 0
for index, i in enumerate(corpus[0]):
decode_counter += 1
corpus.iloc[index][0] = i.decode('UTF-8')
The corpus variable contains the name of the .txt file as an index, and the contents of the individual .txt files in a column named 0. Thank you very much!
Maybe you could try every codec available in your environment and check which result fits best.
Here is a way of doing that:
import os, codecs, encodings
from collections import OrderedDict
from typing import Union
from cprinter import TC
from input_timeout import InputTimeout
class CodecChecker:
def __init__(self):
self.encodingdict = self.get_codecs()
self.results = OrderedDict()
def get_codecs(self):
dir = encodings.__path__[0]
codec_names = OrderedDict()
for filename in os.listdir(dir):
if not filename.endswith(".py"):
continue
name = filename[:-3]
try:
codec_names[name] = OrderedDict({"object": codecs.lookup(name)})
except Exception as Fehler:
pass
return codec_names
def try_open_file(self, path: str, readlines: int = 0):
self.results = OrderedDict()
results = OrderedDict()
if readlines == 0:
for key, item in self.encodingdict.items():
results[key] = {"strict_encoded": [], "strict_bad": True}
try:
with open(path, encoding=key) as f:
data = f.read()
results[key]["strict_encoded"].append(data)
results[key]["strict_bad"] = False
except Exception as fe:
results[key]["strict_encoded"].append(str(fe))
continue
else:
for key, item in self.encodingdict.items():
results[key] = {"strict_encoded": [], "strict_bad": True}
try:
with open(path, encoding=key) as f:
for ini, line in enumerate(f.readlines()):
if ini == readlines:
break
results[key]["strict_encoded"].append(line[:-1])
results[key]["strict_bad"] = False
except Exception as fe:
results[key]["strict_encoded"].append(str(fe))
continue
self.results = results.copy()
return self
def try_convert_bytes(self, variable: bytes):
self.results = OrderedDict()
results = OrderedDict()
modes = ["strict", "ignore", "replace"]
for key, item in self.encodingdict.items():
results[key] = {
"strict_encoded": [],
"strict_bad": True,
"ignore_encoded": [],
"ignore_bad": True,
"replace_encoded": [],
"replace_bad": True,
}
for mo in modes:
try:
results[key][f"{mo}_encoded"].append(
item["object"].decode(variable, mo)
)
results[key][f"{mo}_bad"] = False
except Exception as Fe:
results[key][f"{mo}_encoded"].append(str(Fe))
self.results = results.copy()
return self
def print_results(
self, pause_after_interval: Union[int, float] = 0, items_per_interval: int = 0
):
counter = 0
for key, item in self.results.items():
if pause_after_interval != 0 and items_per_interval != 0:
if items_per_interval == counter and counter > 0:
i = InputTimeout(
timeout=pause_after_interval,
input_message=f"Press any key to continue or wait {pause_after_interval} seconds",
timeout_message="",
defaultvalue="",
cancelbutton=None,
show_special_characters_warning=None,
).finalvalue
counter = 0
print(
f'\n\n\n{"Codec".ljust(20)}: {str(TC(key).bg_cyan.fg_black)}'.ljust(100)
)
if "strict_bad" in item and "strict_encoded" in item:
print(f'{"Mode".ljust(20)}: {TC("strict").fg_yellow.bg_black}')
if item["strict_bad"] is False:
if isinstance(item["strict_encoded"][0], tuple):
if item["strict_bad"] is False:
try:
print(
f"""{'Length'.ljust(20)}: {TC(f'''{item['strict_encoded'][0][1]}''').fg_purple.bg_black}\n{'Converted'.ljust(20)}: {TC(f'''{item['strict_encoded'][0][0]}''').fg_green.bg_black}"""
)
except Exception:
print(
f"""Problems during printing! Raw string: {item['strict_encoded'][0][0]!r}"""
)
if item["strict_bad"] is True:
try:
print(
f"""{'Length'.ljust(20)}: {TC(f'''{"None"}''').fg_red.bg_black}\n{'Converted'.ljust(20)}: {TC(f'''{item['strict_encoded'][0]}''').fg_red.bg_black}"""
)
except Exception:
print(
f"""Problems during printing! Raw string: {item['strict_encoded'][0][0]!r}"""
)
if isinstance(item["strict_encoded"][0], str):
if item["strict_bad"] is False:
itemlen = len("".join(item["strict_encoded"]))
concatitem = "\n" + "\n".join(
[
f"""Line: {str(y).ljust(14)} {str(f'''{x}''')}"""
for y, x in enumerate(item["strict_encoded"])
]
)
try:
print(
f"""{'Length'.ljust(20)}: {TC(f'''{itemlen}''').fg_purple.bg_black}\n{'Converted'.ljust(20)}: {concatitem}"""
)
except Exception:
print(
f"""Problems during printing! Raw string: {concatitem!r}"""
)
if item["strict_bad"] is True:
concatitem = TC(
" ".join(item["strict_encoded"])
).fg_red.bg_black
try:
print(
f"""{'Length'.ljust(20)}: {TC(f'''{"None"}''').fg_red.bg_black}\n{'Converted'.ljust(20)}: {concatitem}"""
)
except Exception:
print(
f"""Problems during printing! Raw string: {concatitem!r}"""
)
print("")
if "ignore_bad" in item and "ignore_encoded" in item:
print(f'{"Mode".ljust(20)}: {TC("ignore").fg_yellow.bg_black}')
if item["ignore_bad"] is False:
if isinstance(item["ignore_encoded"][0], tuple):
if item["ignore_bad"] is False:
try:
print(
f"""{'Length'.ljust(20)}: {TC(f'''{item['ignore_encoded'][0][1]}''').bg_black.fg_lightgrey}\n{'Converted'.ljust(20)}: {TC(f'''{item['ignore_encoded'][0][0]}''').bg_black.fg_lightgrey}"""
)
except Exception:
print(
f"""Problems during printing! Raw string: {item['ignore_encoded'][0][0]!r}"""
)
print("")
if "replace_bad" in item and "replace_encoded" in item:
print(f'{"Mode".ljust(20)}: {TC("replace").fg_yellow.bg_black}')
if item["replace_bad"] is False:
if isinstance(item["replace_encoded"][0], tuple):
if item["replace_bad"] is False:
try:
print(
f"""{'Length'.ljust(20)}: {TC(f'''{item['replace_encoded'][0][1]}''').bg_black.fg_lightgrey}\n{'Converted'.ljust(20)}: {TC(f'''{item['replace_encoded'][0][0]}''').bg_black.fg_lightgrey}"""
)
except Exception:
print(
f"""Problems during printing! Raw string: {item['replace_encoded'][0][0]!r}"""
)
counter = counter + 1
return self
if __name__ == "__main__":
teststuff = b"""This is a test!
Hi there!
A little test! """
testfilename = "test_utf8.tmp"
with open("test_utf8.tmp", mode="w", encoding="utf-8-sig") as f:
f.write(teststuff.decode("utf-8-sig"))
codechecker = CodecChecker()
codechecker.try_open_file(testfilename, readlines=2).print_results(
pause_after_interval=1, items_per_interval=10
)
codechecker.try_open_file(testfilename).print_results()
codechecker.try_convert_bytes(teststuff.decode("cp850").encode()).print_results(
pause_after_interval=1, items_per_interval=10
)
Or you simply run a script to replace all messed up characters. Since I am a German teacher, I have this problem frequently (encoding problems due to Umlaut). Here is a script to replace all characters (too big to post the script here): https://github.com/hansalemaos/LatinFixer/blob/main/__init__.py
I have this script to perform config-backups from juniper-devices based on input from Netbox. I would like to expand this script a little to fetch the firmware version from the juniper device and update our netbox using a custom field.
#!/usr/bin/python3
import sys,os,getopt
from getpass import getpass
from jnpr.junos import Device
import jnpr.junos.facts
from jnpr.junos.utils.config import Config
from jnpr.junos.exception import *
from lxml import etree
from pprint import pprint
import pynetbox
import datetime
nb = pynetbox.api(url='https://netbox-test/', token='<censored>')
save_path = '/config-backups/'
def printProgress(logtype,hostname,message):
print("%s:%s:%s"%(logtype,hostname,message))
def GetConfig(my_hostname, my_username, my_password):
try:
printProgress("INFO",my_hostname,"Connecting to device")
dev=Device(host=my_hostname,user=my_username,password=my_password)
dev.open(auto_probe=10)
dev.timeout=10
printProgress("INFO",my_hostname,"Retrieving config")
config = dev.rpc.get_config(options={'database':'committed','format':'set'})
junos_version = dev.facts['version']
configbackup = (etree.tostring(config, encoding='unicode', pretty_print=True))
completefilename = os.path.join(save_path, my_hostname+".set.config")
outfile=open(completefilename, "w")
outfile.write(configbackup)
dev.close()
outfile.close()
return True,junos_version
except Exception as err:
printProgress("ERROR",my_hostname,"Encountered exception while backing up config")
printProgress("ERROR",my_hostname,str(err))
return False
def main(argv):
junos_password = ''
try:
opts, args = getopt.getopt(argv,"?u:p:",["username=","password"])
except getopt.GetoptError:
print ('configbackup_junos.py -u <username> [-p <junos admin password>]')
sys.exit(2)
for opt, arg in opts:
if opt == '-?':
print ('configbackup_junos.py -u <username> [-p <junos admin password>]')
sys.exit()
elif opt in ("-u", "--username"):
junos_username = arg
elif opt in ("-p", "--password"):
junos_password = arg
print ('Will attempt to backup junos devices documented in Netbox using username:', junos_username)
if len(junos_password) > 0:
print ('Junos Password set on commandline\n')
else:
print ('password not entered, will ask for it')
junos_password=getpass(prompt="\nPassword: ")
nb_devicelist = nb.dcim.devices.all()
for nb_device in nb_devicelist:
platform = str(nb_device.platform)
pri_ip = str(nb_device.primary_ip)
asset = nb_device.asset_tag
devstatus = str(nb_device.status)
backup_enabled = nb_device.custom_fields['backup_enable']
if nb_device.virtual_chassis:
vchassismaster = str(nb_device.virtual_chassis.master)
else:
vchassismaster = 'no_chassis'
if backup_enabled == 'Yes' and platform == 'Junos' and devstatus == 'Active' and pri_ip != 'None' and asset:
if vchassismaster == (nb_device.name) or vchassismaster == 'no_chassis':
if GetConfig(asset,junos_username,junos_password):
print ("Config Successfully backed up from device.",nb_device)
nb_device.custom_fields['backup_status'] = "OK"
timenow = datetime.datetime.now()
timestamp = timenow.strftime("%Y-%m-d %X")
nb_device.custom_fields['backup_timestamp'] = timestamp
nb_device.save()
print (junos_version)
else:
printProgress ("ERROR",nb_device,"Config backup failed! ")
nb_device.custom_fields['backup_status'] = "FAILED"
nb_device.save()
print("")
if len(sys.argv) == 1:
sys.exit()
if __name__ == "__main__":
main(sys.argv[1:])
My problem is how do I get the variable "junos_version" returned from the function GetConfig. As you can see I have tried using "return True,junos_version", but how do I grab it in the output of the function?
(I have read all the articles I could find about this and tried a number of suggestions, but nothing works.
I need to be able to input the "junos_version" into this command
nb_device.custom_fields['firmware_version'] = junos_version
Which I wouldd placee just before the nb_device.save
I suspect it is my sense of logic that fails here, I just cannot see the forest for trees.
if GetConfig(asset,junos_username,junos_password):
you can change this with :
with flag, junos_version=GetConfig(asset,junos_username,junos_password):
If you return multiple values from a function, consider them a tuple.
In your case you can get the second value in the following way:
cfg = GetConfig(...) // add your args
junos_version = cfg[1] // get the 2-nd returned value from a tuple.
First you have to have a stable return.
def GetConfig(my_hostname, my_username, my_password):
try:
...
return True,junos_version
except Exception as err:
...
return False
In here you can have a tuple (of boolean and version) or a bool (True or False) as return.
I would change it as:
def GetConfig(my_hostname, my_username, my_password):
try:
...
return True,junos_version
except Exception as err:
...
return False, None
since there is no junos_version in exception.
Now you change the code where you use it as:
def main(argv):
...
if GetConfig(asset,junos_username,junos_password):
...
to
def main(argv):
...
cfg, version = GetConfig(asset,junos_username,junos_password)
if cfg:
...
I'm still republishing a python 2.x script in 3.x.
at some point, the script must replace the "print" function with "disp" (equivalent in TI basic language) except that it no longer works because of parentheses. anyone have an idea to fix it?
The code :
elif (line.find("print ")==idepth(line)):
line = replace(line,"print ","Disp ")
if (line[-1] == ","):
line = line[:-1].rstrip() # Trailing , not legal for ti basic
thanks in advance
Edit: full code :
import sys
import os
import re
#GUI:
import tkinter as tk
from tkinter import filedialog
import tkinter.simpledialog
import tkinter.messagebox
GUI_MODE = False
TAB_REPLACE = " "
def main():
args = sys.argv[1:]
global GUI_MODE
print (args)
if (len(args)==0):
GUI_MODE=True
root = tk.Tk()
root.withdraw()
inp = filedialog.askopenfilename(title="Select a python script to convert")
if (inp==''):
print ("cancelled")
return 0
else:
inp=args[0]
#now input file is known
file=open(inp)
prog = file.read().replace("\r","").split("\n") # Lines of code
#Get a program name:
if (prog[0][:1]=="#" and (prog[0].upper().find("NAME:")>-1 or prog[0].upper().find("PROGRAM:")>-1 )):
outname=prog[0][prog[0].find(":")+1:]
else:
outname=tkinter.simpledialog.askstring("File name","What do you want to name this program?")
fixed = format(prog)
#Write the converted program in this folder:
print ("\n--Converted to TI-Basic code:--")
print (fixed)
print ("")
print ("Making output files: "+outname+".tib, "+outname+".8xp ...")
#Write the converted program in this folder:
outfile=open(outname+".tib","w")
outfile.write(fixed)
outfile.close()
#Write the .8xp program
outfile=open(outname+".8xp","w")
outfile.write(fixed)
outfile.close()
#assuming the compiler tibasic.exe is in this folder:
if (sys.platform[:3]=="win"):
if (os.system('tibasic.exe '+outname+'.tib')): #Returns non-0, error:
errReport("Error trying to run tibasic.exe! Make sure it is in the current folder.")
else:
if (os.system('wine tibasic.exe '+outname+'.tib')): #Returns non-0, error:
errReport("Error trying to run tibasic.exe! Make sure it is in the current folder, and w.i.n.e is installed.\n"+
"(See http://www.winehq.org/ for installer)")
os.remove(outname+".tib")
a=input("Done! Press enter to exit:") #pause
return 0
def format(linesArray): #converts lines from Python to ti-basic.
for i in range(len(linesArray)):
linesArray[i]=linesArray[i].replace("\t",TAB_REPLACE) #Important! see idepth()
i=0;
linesArray.append("") # 0-indent ending so blockAddEnd won't mess up.
while (i<len(linesArray)):
#Convert control blocks (if, for, while) from indented (python) to END (TI)
line = linesArray[i]
if isBlockStart(line,"for "):
linesArray = blockAddEnd(linesArray, i, "End")
elif isBlockStart(line,"if "):
linesArray = blockAddEnd(linesArray, i, "End")
elif isBlockStart(line,"while "):
linesArray = blockAddEnd(linesArray, i, "End")
elif isBlockStart(line,"repeat "): #not in python, but works on TI.
linesArray = blockAddEnd(linesArray, i, "End")
i+=1
# Don't need indentations anymore, do the rest of the conversions:
for i in range(len(linesArray)):
linesArray[i]=convLine(linesArray[i],i+1)
#Remove blanks:
for i in range(linesArray.count("")):
linesArray.remove("")
return "\n".join(linesArray)
def convLine(line,num): #Line by line conversion.
line = line.rstrip().lstrip() #trim indentation.
lnum = "Line "+str(num)+": "
if line.count("#"):
comment = line[line.find("#"):]
if (comment[0:6] == "#no-ti"):
#Does not work on the ti.
return ""
elif (comment[0:4] == "#ti:"):
# Only for ti:
return comment[4:]
else:
line = line[:line.find("#")] # take comment off code
#No imports in ti-basic!
if line.startswith("import ") or (line.count(" import ") and line.startswith("from ")):
return ""
#Errors and warnings:
if (toolong(line)):
print (lnum+"Warning: Text string too long to fit on a TI83/84 screen. The calculator screen is 16 characters wide, 8 characters high.")
if (line.find("\n")>-1):
print (lnum+"Warning: newline \\n is not allowed in TI-Basic.")
if (line.find("'''")>-1):
print (lnum+"Warning: ''' quotes are not allowed, you must use \" quotes on a single line for TI-Basic.")
if (replace(line,"pow(","")!=line):
errReport(lnum+"TI calculators don't have the pow() command, you must use a**b instead of pow(a,b).")
if (replace(line,"import ","")!=line):
print (lnum+"import ignored. No import statements in TI-Basic!")
return "" # ignore import statements!
if (replace(line,"-=","")!=line):
errReport(lnum+"The -= operator is not allowed.\nTry +=- or a=a+-number instead.")
if (replace(line,"def ","")!=line):
errReport(lnum+"Functions are not supported in TI-Basic! However, you can run another program with \"prgmPRGNAME\".")
if (replace(line,"//","")!=line):
print (lnum+"// division converted to / division: For int division, try int(a/b).")
line=replace(line,"//","/")
if (replace(line,"-","")!=line):
print (lnum+"Warning: The - is changed to negative sign on the calculator. If you wanted to subtract, use a+-b instead of a-b.")
if (replace(line,"open(","")!=line):
errReport(lnum+"Error: TI calculators can't use \"open(filename)\" in programs. To store text, try using variables STR0, STR1, ... STR9.")
if (replace(line,"%","")!=line):
errReport(lnum+"Error: TI83/84 calculators don't have Mod.\n Instead of a % b, try (a/b-int(a/b))*b instead.")
# Replace excess spaces, they cause errors in the calculator:
line=replace(line,", ",",")
line=replace(line," + ","+")
line=replace(line," - ","-")
line=replace(line," +- ","+-")
line=replace(line," * ","*")
line=replace(line," / ","/")
line=replace(line," == ","==")
line=replace(line," > ",">")
line=replace(line," < ","<")
line=replace(line," != ","!=")
#TODO: Arrays converted to lists?
line=replace(line,"theta","[theta]") # variable
line=replace(line,"**","^")
line=mathReplace(line)
#round, max, min already works.
line=replace(line,"float(","(")
line=replace(line,"len(","dim(")
line=replace(line,"math.pi","[pi]")
line=replace(line,"math.e","[e]")
line=replace(line,"eval(","expr(")
line=replace(line,"-","[neg]") # use +- instead of - operator.
line=replace(line,"==","=")
line=replace(line," and ","&")
line=replace(line," or ","|")
line=replace(line,"random.random()","rand")
line=replace(line,"random.randint","RandInt")
line=replace(line,"int(","iPart(")
if (replace(line,"input(","") != line):
line=inputConv(line,num)
if isBlockStart(line,"for "):
line=forConv(line,num)
elif (isBlockStart(line,"if ")):
line = replace(line,"if ","If ")
line = replace(line,":",":Then")
elif (isBlockStart(line,"while ")):
line = replace(line,"while ","While ")
line = replace(line,":","")
elif (isBlockStart(line,"repeat")):
line = replace(line,"repeat","Repeat")
line = replace(line,":","")
elif (isBlockStart(line,"else")):
line = replace(line,"else:","Else")
elif isBlockStart(line,"elif"):
errReport(lnum+"""Error: There is no else-if command on the TI83/84. However, you can use this instead:
if <condition>:
...
else:
if <condition>:
...
else:
...""")
elif (line.find("print ")==idepth(line)):
line = re.sub(r"print *\((.+)\)", r"disp \1", line)
if (line[-1] == ","):
line = line[:-1].rstrip() # Trailing , not legal for ti basic
elif (replace(line,"=","")!=line): #assignment is -> on the calculator.
eqspace = line.find("=")
line = line[eqspace+1:].rstrip().lstrip() + "->" + line[:eqspace].rstrip().lstrip() # sto arrow.
line = fixEQ(line)
return replace(line,"+[neg]","-") #lastly, switch back the negative.
def fixEQ(line):
# fix +=, *=, /=.
# A+=1 changes to 1->A+, so fix it now.
if (line[-1]=="+" or line[-1]=="*" or line[-1]=="/"):
line = line[:-1].rstrip()+line[-1] # remove any spaces in "a +" etc
pre = line[line.find("->")+2:]
#pre = pre[:-1].rstrip()+pre[-1]
line= pre + "("+line[:line.find("->")]+")"+ line[line.find("->"):-1]
return line
def inputConv(line,num):
lnum = "Line "+str(num)+": "
if (replace(line,"raw_input(","")!=line and line==replace(line,"=","")):
#raw_input not assigned to variable is like Pause.
return "Pause "
else:
var = line[:line.find("=")].rstrip().lstrip()
if (len(var)>1 and var!="theta"): # might be invalid.
print (lnum+"Warning: Program tries to store to variable \"%s\"." % var)
prompt = line[line.find("input(")+6:]
prompt = prompt[:prompt.find(")")]
# Now return the TI basic input with var spaces removed:
return "Input "+prompt+","+var
def forConv(line,num):
lnum = "Line "+str(num)+": "
# split "for i in range(...):"
var = line[line.find("for ")+4:line.find(" in range")]
#print var
part = line[line.find("in range(")+9:] # only "...) : "
part = part.rstrip(": ")[:-1] # remove extra " " or ":", remove last ).
#print "'"+line+"'"
out = part.split(",")
if len(out)==1:
return "For(%s,0,(%s)-1)" % (var, out[0])
elif len(out)==2:
return "For(%s,(%s),(%s)-1)" % (var, out[0], out[1])
elif len(out)==3:
return "For(%s,(%s),(%s)-1,(%s)" % (var, out[0], out[1], out[2])
else:
errReport(lnum+"Too many commas in for loop!")
return "couldn't convert: "+line
def blockAddEnd(lines, startLine, endText):
# Takes an array, line #, and end text.
# Adds end for that indentation block.
startInd = idepth(lines[startLine])
if idepth(lines[startLine+1]) <= startInd:
errReport("Expected indent after line "+str(startLine+1)+".")
i = startLine+1
#continue searching for the end while it's indented or it's an else line:
while idepth(lines[i]) > startInd or (isBlockStart(lines[i],"else")):
i+=1
# now insert.
lines.insert(i,endText)
return lines
def idepth(text):
# get indentation depth of line.
depth=0
line = text.replace("\t",TAB_REPLACE) #tab is 4 spaces.
while (line[:1]==" "):
line=line[1:]
depth+=1
return depth
def replace(text, changethis, tothis):
# replaces text, but not in quotes.
arr = text.split("\"")
for i in range(0,len(arr),2):
arr[i]=arr[i].replace(changethis, tothis)
return "\"".join(arr)
def toolong(text):
# checks for too long string:
arr = text.split("\"")
for i in range(1,len(arr),2):
#print arr[i]
if (len(arr[i]) > 16):
return True
return False
def parMatch(text,num): # given "(stuff()...()))", returns the parentheses block.
lnum = "Line "+str(num)+": "
for i in range(len(text)):
part = text[:i-1]
if (part.count("(")==part.count(")")):
return part[1:-1] #without outside parentheses.
errReport(lnum+"Invalid parentheses")
def isBlockStart(line, type):
# Check if the line is start of a <type> block.
# checks if it starts with <type>, and ends with ":".
# example: isBlockStart("for i in range(8) : ","for") is true.
return (line.find(type) == idepth(line) and line.rstrip(" ")[-1]==":")
def errReport(text):
print (text)
if (GUI_MODE):
root = tk.Tk()
root.withdraw()
tkinter.messagebox.showerror("Error",text)
sys.exit(1)
def mathReplace(line):
""" Replaces mathematical functions with ti basic functions. """
#Same function in both Python and TI-basic:
same = ["sin", "cos", "tan", "asin", "acos", "atan", "sinh", "cosh", "tanh", "asinh", "acosh", "atanh"]
line=replace(line,"math.sqrt(","[root]^2(")
line=replace(line,"math.fabs(","abs(")
for func in same:
line = replace(line,"math.%s(" % func,func)
line=replace(line,"math.log(","ln(")
line=replace(line,"math.exp(","e^(")
line=replace(line,"math.floor(","int(")
line=replace(line,"math.log10(","log(")
#same, but without "math." They might use
#from math import sqrt etc...
line=replace(line,"sqrt(","[root]^2(")
line=replace(line,"fabs(","abs(")
for func in same:
line = replace(line, "%s(" % func,func)
#(Redundant lines deleted)
line=replace(line,"log(","ln(")
line=replace(line,"exp(","e^(")
line=replace(line,"floor(","int(")
line=replace(line,"log10(","log(")
return line
if __name__ == '__main__': main()
it's the original code with changement propose below
You can use python's regular expression library to perform more advanced string matching and replacement than replace(). Specifically, re.sub(), which functions the same as replace() but takes regular expressions instead of simple strings.
Be sure to first import it with import re. You can then do the following:
elif (line.find("print ")==idepth(line)):
line = re.sub(r"print *\(\"(.+)\"\)", r"disp \1", line)
if (line[-1] == ","):
line = line[:-1].rstrip() # Trailing , not legal for ti basic
This will look for a string of the format "print("&1")" or "print ("&1")" and replace it with "disp &1", where &1 is the contents between the quotes.
Edit: You had initially specified that you wanted the output "without the quotes", but it seems you've edited that comment. If you want to include the quotes in the output, use this line instead:
line = re.sub(r"print *\((.+)\)", r"disp \1", line)
Not sure if it's possible, but I was hoping to do something where I can print a hyphen for the width of the terminal on one line. If the window's width is resized, the amount of hyphens displayed would print accordingly.
This is a more elaborated version that allows printing whatever you want always according to the dimension of the terminal. You can also resize the terminal while nothing is being printed and the content will be resized accordingly.
I commented the code a little bit... but if you need I can be more explicit.
#!/usr/bin/env python2
import threading
import Queue
import time
import sys
import subprocess
from backports.shutil_get_terminal_size import get_terminal_size
printq = Queue.Queue()
interrupt = False
lines = []
def main():
ptt = threading.Thread(target=printer) # Turn the printer on
ptt.daemon = True
ptt.start()
# Stupid example of stuff to print
for i in xrange(1,100):
printq.put(' '.join([str(x) for x in range(1,i)])) # The actual way to send stuff to the printer
time.sleep(.5)
def split_line(line, cols):
if len(line) > cols:
new_line = ''
ww = line.split()
i = 0
while len(new_line) <= (cols - len(ww[i]) - 1):
new_line += ww[i] + ' '
i += 1
print len(new_line)
if new_line == '':
return (line, '')
return (new_line, ' '.join(ww[i:]))
else:
return (line, '')
def printer():
while True:
cols, rows = get_terminal_size() # Get the terminal dimensions
msg = '#' + '-' * (cols - 2) + '#\n' # Create the
try:
new_line = str(printq.get_nowait())
if new_line != '!##EXIT##!': # A nice way to turn the printer
# thread out gracefully
lines.append(new_line)
printq.task_done()
else:
printq.task_done()
sys.exit()
except Queue.Empty:
pass
# Build the new message to show and split too long lines
for line in lines:
res = line # The following is to split lines which are
# longer than cols.
while len(res) !=0:
toprint, res = split_line(res, cols)
msg += '\n' + toprint
# Clear the shell and print the new output
subprocess.check_call('clear') # Keep the shell clean
sys.stdout.write(msg)
sys.stdout.flush()
time.sleep(.5)
if __name__ == '__main__':
main()
Check this out:(it worked on windows and python3 )
import os
os.system('mode con: cols=100 lines=40')
input("Press any key to continue...")
os.system('mode con: cols=1000 lines=400')
input("Press any key to continue...")
This is doing exactly what you asked for... with a very small issue: when you make the shell smaller the cursor goes down of one line and the stuff that is above will stay there.... I can try to solve this issue... but the result will be more complicated.
I assumed you are using a unix system.
The code uses threads to be able to keep the line on the screen while doing other things. In this case just sleeping... Moreover, only using a thread is actually possible to have a "fast" answer to the change of the dimension of the terminal.
#!/usr/bin/env python2
import threading
import time
import sys
from backports.shutil_get_terminal_size import get_terminal_size
def main1():
ptt = threading.Thread(target=printer2)
ptt.daemon = True
ptt.start()
time.sleep(10)
def printer2():
while True:
cols, rows = get_terminal_size()
line = '-' * (cols - 2)
sys.stdout.write("\r" + '#' + line + '#')
sys.stdout.flush()
time.sleep(.5)