Infinite loop while trying simple indentedBlock expression in pyparsing - pyparsing

I'm trying to parse indented blocks with pyparsing and indentedBlock
Here my code
from pyparsing import *
indent_stack = [1]
line = ungroup(restOfLine)
block = ungroup(indentedBlock(line, indent_stack))
# Work
data = """ foo
bar
tar
"""
block.parseString(data).pprint()
The problem is that parseString won't return. It seems to be waiting for more input or maybe I hit an infinite loop. If I put an unidnented line in the block start to work
data = """ foo
bar
tar
end
"""
But I want to be able to parse up to unindented line (the working case), or to the end of string (the not working case)

This is a bug in pyparsing. indentedBlock uses OneOrMore internally to implement the repetition of the embedded lines. But restOfLine does not fail if it is at the end of a line, and so once you get to the end of the string, indentedBlock's repetition just keeps finding empty restOfLines, and so indentedBlock just loops forever.
A workaround for now, until this bug gets fixed and released, is to change your definition of line from:
line = ungroup(restOfLine)
to
line = ungroup(~StringEnd() + restOfLine)

I couldn't figure out exactly why the code is doing this. I even tried running it in Debug mode and pausing, but it wouldn't even pause so that I could see where it was getting stuck.
A workaround you could use for now is modifying the data to add an unindented line:
from pyparsing import *
indent_stack = [1]
line = ungroup(restOfLine)
block = ungroup(indentedBlock(line, indent_stack))
# Work
data = """ foo
bar
tar
"""
block.parseString(data + "\nend").pprint()
# Result: [['foo'], ['bar'], ['tar']]

Related

How to suppress unwanted Plot figure object information in Jupyter Notebook

I want to suppress any text output when I run Jupyter Notebook cell. Specifically I output some figures and each is accompanied by something like:
<Figure size 432x288 with 0 Axes>
I have seen that if I put a ; at the end of a line, it should suppress the output, but it is not working in my case.
The code:
for i in tqdm_notebook(range(data.shape[0])):
print('BIN:',i)
fig = plt.figure(figsize=(15,4))
plt.tight_layout()
gs = gridspec.GridSpec(2,1)
ax1 = fig.add_subplot(gs[0, 0])
ax1.plot(match[window_begin:window_end],'k')
plt.vlines(i,-np.max(match[window_begin:window_end])*0.05,np.max(match[window_begin:window_end])*1.05,'r',linewidth=4,alpha=0.2)
ax1.set_xlim(0-1,post_bin_match_median[window_begin:window_end].shape[0])
ax1.set_ylim(-np.max(match[window_begin:window_end])*0.05,np.max(match[window_begin:window_end])*1.05)
plt.tick_params(axis='y', which='both', left=True, labelleft=False)
ax1.tick_params(axis='x', which='both', bottom=False, labelbottom=False)
plt.grid()
ax2 = fig.add_subplot(gs[1, 0])
fig.subplots_adjust(hspace=0.0)
ax2.plot(gp_mjds[:],gp_data[i,:],'k')
ax2.errorbar(remain, all[i,:], yerr=all_noise[i], fmt=".k", capsize=0);
ax2.fill_between(gp[:], gp2[i,:] - np.sqrt(gp_var[i,:]), gp2[i,:] + np.sqrt(gp_var[i,:]),color="k", alpha=0.2)
ax2.set_xlim(gp[0],gp[-1])
plot_y_min = np.minimum(np.min(gp2[:,:] - np.sqrt(gp_var[:,:])),np.min(all_profile_residuals[:,:]-y_noise))
plot_y_max = np.maximum(np.max(gp2[:,:] + np.sqrt(gp_var[:,:])), np.max(all[:,:]+y_noise))
ax2.set_ylim(plot_y_min,plot_y_max)
plt.grid()
plt.show()
plt.clf()
plt.close(fig);
The semi-colon would work if the typical output from the last line of the cell is what you are trying to suppress. As succinctly summarized by #kynan here, "The reason this works is because the notebook shows the return value of the last command. By adding ; the last command is "nothing" so there is no return value to show."
However, you have a loop inside a cell generating objects.
The culprit seems to be plt.clf(). Comment out that line or remove it from your code, and it should fix it.
Plus, I'd remove plt.show() as it isn't necessary when plt.clf() is removed, and I am seeing it being in the loop causing fig = plt.figure(figsize=(15,4)) to also show output text like you posted in your issue.
(I'll add for others looking at this later, that it is important have %matplotlib inline or %matplotlib notebook at the start of the cell (or at the start of a cell somewhere above this one.))
A complete guide on how to hide or remove content in Jupyter is available from the official documentation: https://jupyterbook.org/interactive/hiding.html#
For removing the single output line, you can tweak the command lines by adding a _ = [command ] assignment as suggested in this blog: https://www.tutorialguruji.com/python/suppress-output-in-matplotlib/.
The underscore there is a throwaway variable, actually an unidentified variable "when not in interactive mode". See the official Python documentation: https://docs.python.org/3.9/reference/lexical_analysis.html#reserved-classes-of-identifiers

Shortening .write commands

I am learning from the book Learn Python The Hard Way 3.6, by Zed Shaw
There are a series of 6 target.write commands towards the bottom of the script and he wants me to simplify them into a single target.write command using strings formats and escapes. However, I am stuck.
Here is the original code:
from sys import argv
script, filename = argv
print(f"We're going to erase {filename}")
print("If you don't want that, hit CTRL-C (^C).")
print("If you do want that, hit RETURN.")
input("?")
print("Opening the file...")
target = open(filename,'w')
print("Truncating the file. Goodbye!")
target.truncate()
print("Now I'm going to ask you for three lines")
line1 = input("line 1:")
line2 = input("line 2:")
line3 = input("line 3:")
print("Im going to write these to the file.")
target.write(line1)
target.write("\n")
target.write(line2)
target.write("\n")
target.write(line3)
target.write("\n")
print("And finnaly, we close it")
target.close()
So far I have tried
target.write(line1),(line2),(line3)
but this gives a logical error of only writing to one line not all three.
target.write(line1) + (line2) + (line3)
with this one I get error
'unsupported operand types for +: 'int' + 'str'
target.write(line1),\n,(line2)\n(line3),\n
with this one I get error:
unexpected character after line continuation character
(<string>,line 22)
I have been googling and searching here for answers but have not found anything. One person posted a very similar question except for Zed's 2.7 book. However I am reading Zed's 3.6 book so the answers were no help to me unfortunately.
I'm not sure what you have and haven't covered so far in the book as I'm not familiar with it but one way to do what you want is to format the string first and then pass it to the write method like this:
target.write("{0}\n{1}\n{2}\n".format(line1, line2, line3))

Python Interpreting things from document

So, I am essentially just dreaming up ideas right now.
I was wondering if it was possible to make a python program that can read a document, take a line from the document, make an if/else statement with it (Like if the text on that line is equal to Hello, than say hello back), and then continue onto the next line. I have already kind of done this in a shell fashion but I want to see if it is possible to have python read the line of a document, interpret it, display something, and move on to the next line of the document.
(I am prepared for this post to get tons of -1's for not knowing how to program a lot of python, and probably just not being clear enough. So before you -1, just add a comment saying what you need me to be clear about.)
The version of python of my choice would be 2.5.
Since you don't know any Python, try this:
with open("file.txt") as f:
for line in f:
if line.strip() == "Hello":
print "Hello back"
or without the exception-safe clause:
for line in open("file.txt"):
if line.strip() == "Hello":
print "Hello back"
the strip() removes the ending newline \n from the line
That is actually a very simple task in Python:
file = open("file.txt") # open the file
while True:
word = file.readline() # read a line from the file
print word # print it to the console
if word == "": # if out of words...
file.close() # ...close the file
break # and break from while loop and exit program

How to edit the last few characters of a file?

I'm making a small program to trace the execution flow of a program. I have some files that have source code and some that don't. For calls that happen in files without source, I'm trying to count them and tack that number to the end of the output line.
From what I understand I'm positioning the cursor 3 characters from the end and then when I write output to myfile, it should have overwritten the previous 3 characters. But when I look in the file, those 3 characters are just getting appended to the end.
with open("C:\\Windows\\Temp\\trace.html", "a+") as myfile:
if hasNoSource and not fileHasChanged:
myfile.seek(-3,2)
output = line
else:
self.noSourceCallCount = 0
myfile.write(output)
return self.lineHook
"a+" mode is open for append mode and any changes by seek() will be reset by next write(). Use "r+" mode.
fileinput module with the inplace option allows you to modify your file but be sure to make a backup if all hell break loose
import fileinput,sys,re
line_count=0
for line in open(my_file):
line_count+=1 # count total lines in file
f=fileinput.input(my_file,inplace=True)
for line in f:
line_count-=1 #when iterating through every line decrement line_count by 1
if line_count==0:
line=re.sub("...$",<replacement>,line) #use regex to replace first three characters in the last line
sys.stdout.write(line) #print line to sys.stdout which will automatically make the changes to this line in file.
else:
sys.stdout.write(line)

How to make a non-blocking pipe from the command-line in Solaris?

I'm trying to write a lua script that reads input from other processes and analyzes it. For this purpose I'm using io.popen and it works as expected in Windows, but on Unix(Solaris) reading from io.popen blocks, so the script just waits there until something comes along instead of returning immediately...
As far as I know I can't change the functionality of io.popen from within the script, and if at all possible I would rather not have to change the C code, because then the script will then need to be bound with the patched binary.
Does that leave me with any command-line solutions?
Ok got no answers so far, but for posterity if someone needs a similar solution I did the following more or less
function my_popen(name,cmd)
local process = {}
process.__proc = assert(io.popen(cmd..">"..name..".tmp", 'r'))
process.__file = assert(io.open(name..".tmp", 'r'))
process.lines = function(self)
return self.__file:lines()
end
process.close = function(self)
self.__proc:close()
self.__file:close()
end
return process
end
proc = my_popen("somename","some command")
while true
--do stuf
for line in proc:lines() do
print(line)
end
--do stuf
end
Your problems seems to be related to buffering. For some reason the pipe is waiting for some data to be read before it allows the opened program to write more to it, and it seems to be less than a line. What you can do is use io.popen(cmd):read"*a" to read everything. This should avoid the buffering problem. Then you can split the returned string in lines with for line in string.gmatch("[^\n]+") do someting_with(line) end.
Your solution consist in dumping the output of the process to a file, and reading that file. You can replace your use or io.popen with io.execute, and discard the return value (just check it's 0).

Resources