I am trying to automate autograding with nbgrader. Usually the student writes a piece of code (like a variable or a function) in the autograded answer cell that the instructor uses (by referring to the variable or function) to write autograder tests.
But some times the input code from the autograded answer cell can be just a print(...) which outputs something to the screen (rather than a variable or function). In that case how is it possible to capture the printed output so that we can use it the next cell for writing autograder tests on it ?
The nbgrader docs include an example demonstrating how to patch the builtin function print so you can capture and test printed output:
Problem: verify that a function call results in the printing of a certain result
def foo()
#...
print('right result')
The test code for this can be written as
from unittest.mock import patch
with patch('__main__.print') as mock_print:
foo()
mock_print.assert_called_once_with('right_result')
This test passes silently if the print is correct, but if the print is wrong:
def foo()
#...
print('wrong result')
an assertion error is raised with output of the form
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
...
AssertionError: Expected call: print('right result')
Actual call: print('wrong result')
Related
I've written a prime-generating function generatePrimes (full code here) that takes input bound::Int64 and returns a Vector{Int64} of all primes up to bound. After the function definition, I have the following code:
println("Generating primes...")
println("Last prime: ", generatePrimes(10^7)[end])
println("Primes generated.")
which prints, unexpectedly,
Generating primes...
9999991
Primes generated.
This output misses the "Last prime: " segment of the second print statement. The output does work as expected for smaller inputs; any input at least up to 10^6, but somehow fails for 10^7. I've tried several workarounds for this (e.g. assigning the returned value or converting it to a string before calling it in a print statement, combining the print statements, et cetera) and discovered some other weird behaviour: if the "Last prime", is removed from the second print statement, for input 10^7, the last prime doesn't print at all and all I get is a blank line between the first and third print statements. These issues are probably related, and I can't seem to find anything online about why some print statements wouldn't work in Julia.
Thanks so much for any clarification!
Edit: Per DNF's suggestion, following are some reductions to this issue:
Removing the first and last print statements doesn't change anything -- a blank line is always printed in the case I outlined and each of the cases below.
println(generatePrimes(10^7)[end]) # output: empty line
Calling the function and storing the last index in a variable before calling println doesn't change anything either; the cases below work exactly the same either way.
lastPrime::Int = generatePrimes(10^7)[end]
println(lastPrime) # output: empty line
If I call the function in whatever form immediately before a println, an empty line is printed regardless of what's inside the println.
lastPrime::Int = generatePrimes(10^7)[end]
println("This doesn't print") # output: empty line
println("This does print") # output: This does print
If I call the function (or print the pre-generated-and-stored function result) inside a println, anything before the function call (that's also inside the println) isn't printed. The 9999991 and anything else there may be after the function call is printed only if there is something else inside the println before the function call.
# Example 1
println(generatePrimes(10^7)[end]) # output: empty line
# Example 2
println("This first part doesn't print", generatePrimes(10^7)[end]) # output: 9999991
# Example 3
println("This first part doesn't print", generatePrimes(10^7)[end], " prints") # output: 9999991 prints
# Example 4
println(generatePrimes(10^7)[end], "prime doesn't print") # output: prime doesn't print
I could probably list twenty different variations of this same thing, but that probably wouldn't make things any clearer. In every single case version of this issue I've seen so far, the issue only manifests if there's that function call somewhere; println prints large integers just fine. That said, please let me know if anyone feels like they need more info. Thanks so much!
Most likely you are running this code from Atom Juno which recently has some issues with buffering standard output (already reported by others and I also sometimes have this problem).
One thing you can try to do is to flush your standard output
flush(stdout)
Like with any unstable bug restarting Atom Juno also seems to help.
I had the same issue. For me, changing the terminal renderer (File -> Settings -> Packages -> julia-client -> Terminal Options) from webgl to canvas (see pic below) seems to solve the issue.
change terminal renderer
I've also encountered this problem many times. (First time, it was triggered after using the debugger. It is probably unrelated but I have been using Julia+Juno for 2 weeks prior to this issue.)
In my case, the code before the println statement needed to have multiple dictionary assignation (with new keys) in order to trigger the behavior.
I also confirmed that the same code ran in Command Prompt (with same Julia interpreter) prints fine. Any hints about how to further investigate this will be appreciated.
I temporarily solve this issue by printing to stderr, thinking that this stream has more stringent flush mechanism: println(stderr, "hello!")
I have a script that defines a function, and later intended to call the function but forgot to add the parentheses, like this:
function myfunc()
println("inside myfunc")
end
myfunc # This line is silently ignored. The function isn't invoked and there's no error message.
After a while I did figure out that I was missing the parentheses, but since Julia didn't give me an error, I'm wondering what that line is actually doing? I'm assuming that it must be doing something with the myfunc statement, but I don't know Julia well enough to understand what is happening.
I tried --depwarn=yes but don't see a julia command line switch to increase the warning level or verbosity. Please let me know if one exists.
For background context, the reason this came up is that I'm trying to translate a Bash script to Julia, and there are numerous locations where an argument-less function is defined and then invoked, and in Bash you don't need parentheses after the function name to invoke it.
The script is being run from command line (julia stub.jl) and I'm using Julia 1.0.3 on macOS.
It doesn't silently ignore the function. Calling myfunc in an interactive session will show you what happens: the call returns the function object to the console, and thus call's the show method for Function, showing how many methods are currently defined for that function in your workspace.
julia> function myfunc()
println("inside myfunc")
end
myfunc (generic function with 1 method)
julia> myfunc
myfunc (generic function with 1 method)
Since you're calling this in a script, show is never called, and thus you don't see any result. But it doesn't error, because the syntax is valid.
Thanks to DNF for the helpful comment on it being in a script.
It does nothing.
As in c, an expression has a value: in c the expression _ a=1+1; _ has the value _ 2 _ In c, this just fell out of the parser: they wanted to be able to evaluate expressions like _ a==b _
In Julia, it's the result of designing a language where the code you write is handled as a data object of the language. In Julia, the expression "a=1+1" has the value "a=1+1".
In c, the fact that
a=1+1;
is an acceptable line of code means that, accidentally,
a;
is also an acceptable line of code. The same is true in Julia: the compiler expects to see a data value there: any data value you put may be acceptable: even for example the data value that represents the calculated value returned by a function:
myfunc()
or the value that represents the function object itself:
myfunc
As in c, the fact that data values are everywhere in your code just indicates that the syntax allows data values everywhere in your code and that the compiler does nothing with data values that are everywhere in your code.
Robot is telling me that I'm providing too many arguments to my keyword. I've boiled it down to a base case where I have a keyword that should do nothing:
def do_nothing():
"""
Does absolutly nothing
"""
Calling this keywork like this:
*** Test Cases ***
testCaseOne
do_nothing
Give this result:
TypeError: do_nothing() takes no arguments (1 given)
Adding a parameter to the keyword definition fixes the problem. Why does robot seem to pass 1 parameter to each keyword, even if there are no parameters in the test case?
I found the answer here.
The issue has nothing to do with the robotframework, and has every thing to do with Python; Python implicitly passes the current instance of the class to method calls, but I needed to explicitly declare the parameter. This is customarily named self:
def do_nothing(self):
This test runs.
Every time I call a constructor for a custom-type, the show method for that type runs. I cannot work out why. Reproducible example follows:
I have a module:
module ctbTestModule1
import Base.show
export MyType1
type MyType1
function MyType1()
new()
end
end
function show(io::IO, a::MyType1)
println("hello world")
end
end
I open up a fresh julia session in the REPL and type:
using ctbTestModule1
z = MyType1()
The following prints to the console when I run the line z = MyType1():
hello world
How is the show method being called here? It certainly doesn't appear to be called in the inner constructor...
The REPL (Read-evaluate-print loop) evaluates and prints every statement.
What you describe is the usual behavior.
Run z = 1 in your REPL and the printed output will be 1.
Likewise, your z is a MyType1 which is displayed as hello world.
If you want to suppress the output in the REPL finish your statement with a semicolon ;:
z = MyType1();
So, to answer your question: Yes, if you create an instance of a type in the REPL, the result is shown by calling the show() function of that type.
How can output to stdout be suppressed?
A semi-colon can be used to supress display of returned objects, for example
>>> 1+1
2
>>> 1+1; # No output!
However, a function that prints to stdout is not affected by the semi-colon.
>>> print('Hello!')
Hello!
>>> MyFunction()
Calculating values...
How can the output from print / MyFunction be suppressed?
Add %%capture as the first line of the cell. eg
%%capture
print('Hello')
MyFunction()
This simply discards the output, but the %%capture magic can be used to save the output to a variable - consult the docs
Suppress output
Put a ; at the end of a line to suppress the printing of output [Reference].
A good practice is to always return values from functions rather than printing values inside a function. In that case, you have the control; if you want to print the returned value, you can; otherwise, it will not be printed just by adding a ; after the function call.
(credit: https://stackoverflow.com/a/23611571/389812)
You could use io.capture_output:
from IPython.utils import io
with io.capture_output() as captured:
MyFunction()
to supress (e.g. capture) stdout and stderr for those lines within the with-statement.
If anyone is interested in clearing all outputs:
Go to Cell
Go to All Output
Then choose whichever option you like.