Python 2.6.6: Binding print to any other function causes 'Syntax Error' - python-2.6

I'm trying to implement a basic debugging flag into my code. I'm planning on doing this by binding print to logFile.write so instead of logging the process my code executes, it'll print it so the user can see it done and see where it may mess up. I do the same technique by binding raw_input to input for backwards compatibility for python 2 and python 3, but when I try binding print to anything, I get a Syntax Error.
On Python 3 on Windows the line runs correctly, but when run on python 2 on UNIX or Windows it fails.
# If user has passed the 'debug' parameter then no log file will be created and instead will be printed in terminal
if (len(sys.argv) > 1 and sys.argv[1] == 'debug') or (len(sys.argv) > 2 and (sys.argv[1] == 'debug' or sys.argv[2] == 'debug')):
try:
logFile.write = print
except:
print('Debug is not working at this time')
This is the error I receive
SyntaxError: invalid syntax
lax94t01> ./Automation.py userconfig.ini debug
File "./Automation.py", line 55
logFile.write = print
^

Related

Can you output your custom exception message but not the default as well in Ruby?

I have been trying to create exception handling for opening a file in ruby. I have tried to use the raise and rescue method but all types have either shown the custom and the default(instead of just the custom) or have errored out completely. My attempted code
output showing custom one bottom but default on top I want to get rid of
It's because system doesn't raise an exception, it just has varying return values:
system returns true if the command gives zero exit status, false for non zero exit status. Returns nil if command execution fails. An error status is available in $?.
So you can see that it isn't Ruby printing the error message, it's the open command. It's easy to test in your shell:
$ open bar
The file /Users/foo/bar does not exist.
$ echo $?
1
Confirm in Ruby:
system 'open bar'
The file /Users/foo/bar does not exist.
=> false
puts $?
pid 9610 exit 1
=> nil
So there's nothing to rescue because there's no exception ever raised. You have to evaluate the return value of system or the exit code of the process ($?) to make a determination as to the success or failure of your call to system.
If you don't want to see any output at all from open then use this to redirect:
system 'open foo > /dev/null 2>&1'
=> false

Use Bash's select from within Python

The idea of the following was to use Bash's select from Python, e.g. use Bash select to get the input from the user, communicate with the Bash script to get the user selections and use it afterwords in the Python code. Please tell me if it at least possible.
Have the following simple Bash script:
#!/bin/bash -x
function select_target {
target_list=("Target1" "Target2" "Target3")
PS3="Select Target: "
select target in "${target_list[#]}"; do
break
done
echo $target
}
select_target
it works standalone
Now I tried to call it from Python like this:
import tempfile
import subprocess
select_target_sh_func = """
#!/bin/bash
function select_target {
target_list=(%s)
PS3="Select Target: "
select target in "${target_list[#]}"; do
break
done
echo $target
}
select_target
"""
target_list = ["Target1", "Target2", "Target3"]
with tempfile.NamedTemporaryFile() as temp:
temp.write(select_target_sh_func % ' '.join(map(lambda s : '\"%s\"' % str(s),target_list)))
subprocess.call(['chmod', '0777', temp.name])
sh_proc = subprocess.Popen(["bash", temp.name], stdout=subprocess.PIPE)
(output, err) = sh_proc.communicate()
exit_code = sh_proc.wait()
print output
It does nothing. No output, no selection.
I'm using High Sierra MacOS, PyCharm and Python 2.7.
PS
After some reading and experimenting ended up with the following:
with tempfile.NamedTemporaryFile() as temp:
temp.write(select_target_sh_func % ' '.join(map(lambda s : '\"%s\"' % str(s),target_list)))
temp.flush()
# bash: /var/folders/jm/4j4mq_w52bx2l5qwg4gt44580000gn/T/tmp00laDV: Permission denied
subprocess.call(['chmod', '0500', temp.name])
sh_proc = subprocess.Popen(["bash", "-c", temp.name], stdout=subprocess.PIPE)
(output, err) = sh_proc.communicate()
exit_code = sh_proc.wait()
print output
It behaves as I expected it would, the user is able to select the 'target' by just typing the number. My mistake was that I forgot to flush.
PPS
The solution works for MacOS X High Sierra, sadly it does not for Debian Jessie complaining the following:
bash: /tmp/tmpdTv4hp: Text file busy
I believe it is because `with tempfile.NamedTemporaryFile' keeps the temp file open and this somehow prevents Bash from working with it. This renders the whole idea useless.
Python is sitting between your terminal or console and the (noninteractive!) Bash process you are starting. Furthermore, you are failing to direct the standard output pipe anywhere, so subprocess.communicate() actually cannot capture standard error (and if it could, you would not be able to see the script's menu).
Running an interactive process programmatically is a nontrivial scenario; you'll want to look at pexpect or just implement your own select command in Python - I suspect this is going to turn out to be the easiest solution (trivially so if you can find an existing library).

'Bad file mode' error OPEN statement read/write to serial (COM) port using VB6

I try to migrate an old QBasic program, for reading from a serial device (COM-port), to Visual Basic 6.
I use this code (this original code should work for VB6 also):
RESET
OPEN "COM1:2400,E,7,2,CS,DS,CD" FOR RANDOM AS #1
PRINT #1, "SND1"
LINE INPUT #1, P$
This works fine with QBasic (sending 'SND1' gives me the data from the device), but VB6 gives an error at the PRINT-command: 'Bad file mode' (error 54).
If I change FOR RANDOM to FOR OUTPUT the PRINT-commands works, but then the LINE INPUT-command gives the same error (of course).
UPDATE:
The only options for 'mode' (see: http://msdn.microsoft.com/en-us/library/aa266177(v=vs.60).aspx) are Append, Binary, Input, Output, or Random.
Try:
OPEN "COM1:2400,E,7,2,CS,DS,CD" FOR OUTPUT AS #1
PRINT #1, "SND1"
CLOSE #1
OPEN "COM1:2400,E,7,2,CS,DS,CD" FOR INPUT AS #1
LINE INPUT #1, P$
This snip describes using GET/PUT to access a file opened for RANDOM in QB:
OPEN "COM1:9600,N,8,1,BIN,CS0,DS0" FOR RANDOM AS #1
DO
IF LOC(1) THEN
GET 1, , x
PRINT CHR$(x);
END IF
x$ = INKEY$
IF LEN(x$) THEN
IF x$ = CHR$(27) THEN END
x = ASC(x$)
PUT 1, , x
END IF
LOOP
END

Security Tube Python Scripting Expert

I'm currently doing a python course through Security Tube. I've currently got stuck on one module where I have to run a Python script through XP and execute it through Immunity Debugger with a process in front of it.
Here's the code:
#!/usr/bin/python2.7
import immlib
DESC="Find Instructions"
def main(args) :
imm = immlib.Debugger()
assembledInstruction = imm.assemble (' ' .join(args))
if not assembledInstruction :
return "[-] No Instruction Given!"
addressList = imm.search(assembledInstruction)
td = imm.createTable("Instruction Locations", ['Module', 'Base Address', 'Instruction Address', 'Instruction']
for address in addressList :
# Get module for this address
module = imm.findModule(address)
if not module:
imm.log("Address 0x%08X not in any module" %address)
# Get module object by name. Please note we are not checking for page properties.
# exercises? :)
instruction = ''
numArgs = len(' '.join(args).split('\n'))
for count in range(0, numArgs) :
instruction += imm.disasmForward(address, nlines=count).getDisasm() + ''
td.add(0, [ module[0],
str('0x%08X'%module[1])
str('0x%08X'%address),
instruction
])
I've saved the .py file as spse-find.py. From there I log on to my XP through Virtual Box, open Immunity Debugger, execute Server-strcpy.exe. At the bottom of the program, I type in:
!spse-find jmp ecp
But upon this being executed I receive the following error:
pycommands: error importing module.
I've placed this in the Security Tube forums but the only thing which I've been told is that I should check the code syntax to ensure it's correct and to ensure that I'm following the video correctly. I've made the checks at least 4 or 5 times. I haven't received any further replies from them since that and so I was wondering if anyone would be able to provide me with any further insight to where I've gone wrong or where more code needs to be added.
Running your code, I get a SyntaxError:
C:\Users\kevin>test.py
File "C:\Users\kevin\test.py", line 20
for address in addressList :
^
SyntaxError: invalid syntax
This message is misleading, because that line is error-free. But sometimes the reported line number is off by one, so let's look at the previous line:
td = imm.createTable("Instruction Locations", ['Module', 'Base Address', 'Instruction Address', 'Instruction']
This is a syntax error. You are missing a closing parenthesis. It should be:
td = imm.createTable("Instruction Locations", ['Module', 'Base Address', 'Instruction Address', 'Instruction'])
Running the program again, we get:
C:\Users\kevin>test.py
File "C:\Users\kevin\test.py", line 38
str('0x%08X'%address),
^
SyntaxError: invalid syntax
This is another red herring. You forgot a comma on line 37.
str('0x%08X'%module[1])
Should be
str('0x%08X'%module[1]),
That should fix all of your syntax errors. (I can't vouch for the correctness of the program at run time, however, since I don't have the immlib library.)
Using immunity debugger is complicated to find out what is going on. The best way is calling the pycommand without the .py extension. That is, if your pycommand is correctly placed under the PyCommands folder and it is called "example.py", using the command bar at the bottom of the grafical interface you should call the pycommand in this way: !example --> instead of !example.py. The second option will compile the code and just tell you something is wrong, the first one will parse the content and tell you the line which is causing the script to fail.
I hope it helps.
Regards.

How to get R script line numbers at error?

If I am running a long R script from the command line (R --slave script.R), then how can I get it to give line numbers at errors?
I don't want to add debug commands to the script if at all possible; I just want R to behave like most other scripting languages.
This won't give you the line number, but it will tell you where the failure happens in the call stack which is very helpful:
traceback()
[Edit:] When running a script from the command line you will have to skip one or two calls, see traceback() for interactive and non-interactive R sessions
I'm not aware of another way to do this without the usual debugging suspects:
debug()
browser()
options(error=recover) [followed by options(error = NULL) to revert it]
You might want to look at this related post.
[Edit:] Sorry...just saw that you're running this from the command line. In that case I would suggest working with the options(error) functionality. Here's a simple example:
options(error = quote({dump.frames(to.file=TRUE); q()}))
You can create as elaborate a script as you want on an error condition, so you should just decide what information you need for debugging.
Otherwise, if there are specific areas you're concerned about (e.g. connecting to a database), then wrap them in a tryCatch() function.
Doing options(error=traceback) provides a little more information about the content of the lines leading up to the error. It causes a traceback to appear if there is an error, and for some errors it has the line number, prefixed by #. But it's hit or miss, many errors won't get line numbers.
Support for this will be forthcoming in R 2.10 and later. Duncan Murdoch just posted to r-devel on Sep 10 2009 about findLineNum and setBreapoint:
I've just added a couple of functions to R-devel to help with
debugging. findLineNum() finds which line of which function
corresponds to a particular line of source code; setBreakpoint() takes
the output of findLineNum, and calls trace() to set a breakpoint
there.
These rely on having source reference debug information in the code.
This is the default for code read by source(), but not for packages.
To get the source references in package code, set the environment
variable R_KEEP_PKG_SOURCE=yes, or within R, set
options(keep.source.pkgs=TRUE), then install the package from source
code. Read ?findLineNum for details on how to tell it to search
within packages, rather than limiting the search to the global
environment.
For example,
x <- " f <- function(a, b) {
if (a > b) {
a
} else {
b
}
}"
eval(parse(text=x)) # Normally you'd use source() to read a file...
findLineNum("<text>#3") # <text> is a dummy filename used by
parse(text=)
This will print
f step 2,3,2 in <environment: R_GlobalEnv>
and you can use
setBreakpoint("<text>#3")
to set a breakpoint there.
There are still some limitations (and probably bugs) in the code; I'll
be fixing thos
You do it by setting
options(show.error.locations = TRUE)
I just wonder why this setting is not a default in R? It should be, as it is in every other language.
Specifying the global R option for handling non-catastrophic errors worked for me, along with a customized workflow for retaining info about the error and examining this info after the failure. I am currently running R version 3.4.1.
Below, I've included a description of the workflow that worked for me, as well as some code I used to set the global error handling option in R.
As I have it configured, the error handling also creates an RData file containing all objects in working memory at the time of the error. This dump can be read back into R using load() and then the various environments as they existed at the time of the error can be inspected interactively using debugger(errorDump).
I will note that I was able to get line numbers in the traceback() output from any custom functions within the stack, but only if I used the keep.source=TRUE option when calling source() for any custom functions used in my script. Without this option, setting the global error handling option as below sent the full output of the traceback() to an error log named error.log, but line numbers were not available.
Here's the general steps I took in my workflow and how I was able to access the memory dump and error log after a non-interactive R failure.
I put the following at the top of the main script I was calling from the command line. This sets the global error handling option for the R session. My main script was called myMainScript.R. The various lines in the code have comments after them describing what they do. Basically, with this option, when R encounters an error that triggers stop(), it will create an RData (*.rda) dump file of working memory across all active environments in the directory ~/myUsername/directoryForDump and will also write an error log named error.log with some useful information to the same directory. You can modify this snippet to add other handling on error (e.g., add a timestamp to the dump file and error log filenames, etc.).
options(error = quote({
setwd('~/myUsername/directoryForDump'); # Set working directory where you want the dump to go, since dump.frames() doesn't seem to accept absolute file paths.
dump.frames("errorDump", to.file=TRUE, include.GlobalEnv=TRUE); # First dump to file; this dump is not accessible by the R session.
sink(file="error.log"); # Specify sink file to redirect all output.
dump.frames(); # Dump again to be able to retrieve error message and write to error log; this dump is accessible by the R session since not dumped to file.
cat(attr(last.dump,"error.message")); # Print error message to file, along with simplified stack trace.
cat('\nTraceback:');
cat('\n');
traceback(2); # Print full traceback of function calls with all parameters. The 2 passed to traceback omits the outermost two function calls.
sink();
q()}))
Make sure that from the main script and any subsequent function calls, anytime a function is sourced, the option keep.source=TRUE is used. That is, to source a function, you would use source('~/path/to/myFunction.R', keep.source=TRUE). This is required for the traceback() output to contain line numbers. It looks like you may also be able to set this option globally using options( keep.source=TRUE ), but I have not tested this to see if it works. If you don't need line numbers, you can omit this option.
From the terminal (outside R), call the main script in batch mode using Rscript myMainScript.R. This starts a new non-interactive R session and runs the script myMainScript.R. The code snippet given in step 1 that has been placed at the top of myMainScript.R sets the error handling option for the non-interactive R session.
Encounter an error somewhere within the execution of myMainScript.R. This may be in the main script itself, or nested several functions deep. When the error is encountered, handling will be performed as specified in step 1, and the R session will terminate.
An RData dump file named errorDump.rda and and error log named error.log are created in the directory specified by '~/myUsername/directoryForDump' in the global error handling option setting.
At your leisure, inspect error.log to review information about the error, including the error message itself and the full stack trace leading to the error. Here's an example of the log that's generated on error; note the numbers after the # character are the line numbers of the error at various points in the call stack:
Error in callNonExistFunc() : could not find function "callNonExistFunc"
Calls: test_multi_commodity_flow_cmd -> getExtendedConfigDF -> extendConfigDF
Traceback:
3: extendConfigDF(info_df, data_dir = user_dir, dlevel = dlevel) at test_multi_commodity_flow.R#304
2: getExtendedConfigDF(config_file_path, out_dir, dlevel) at test_multi_commodity_flow.R#352
1: test_multi_commodity_flow_cmd(config_file_path = config_file_path,
spot_file_path = spot_file_path, forward_file_path = forward_file_path,
data_dir = "../", user_dir = "Output", sim_type = "spot",
sim_scheme = "shape", sim_gran = "hourly", sim_adjust = "raw",
nsim = 5, start_date = "2017-07-01", end_date = "2017-12-31",
compute_averages = opt$compute_averages, compute_shapes = opt$compute_shapes,
overwrite = opt$overwrite, nmonths = opt$nmonths, forward_regime = opt$fregime,
ltfv_ratio = opt$ltfv_ratio, method = opt$method, dlevel = 0)
At your leisure, you may load errorDump.rda into an interactive R session using load('~/path/to/errorDump.rda'). Once loaded, call debugger(errorDump) to browse all R objects in memory in any of the active environments. See the R help on debugger() for more info.
This workflow is enormously helpful when running R in some type of production environment where you have non-interactive R sessions being initiated at the command line and you want information retained about unexpected errors. The ability to dump memory to a file you can use to inspect working memory at the time of the error, along with having the line numbers of the error in the call stack, facilitate speedy post-mortem debugging of what caused the error.
First, options(show.error.locations = TRUE) and then traceback(). The error line number will be displayed after #

Resources