I dont have much experience with IDL but i need to fix a bug where in the compilation failure status needs to be returned to the calling script.
cat << ENDCAT > something.pro
PRINT, "Start"
PRINT, "Compiling functions needing early compile"
#do_early_func
PRINT, "Compiling remaining functions"
#do_other_func
PRINT, "Running: resolve_all"
resolve_all
EXIT
ENDCAT
setenv IDL_STARTUP something.pro
$IDL_DIR/bin/idl
The above content exists in a script called make_program which is called by another script called the build_script
The problem i am facing is that even if 'resolve_all' results in a compilation failure, the make_program always returns a true to the build_script making it think the compilation succeeded when it actually didnt. How can i return the failure status back to the calling script?
The EXIT routine has a STATUS keyword that can return the exit status of the script. So something like:
exit, status=status_code
To determine if RESOLVE_ALL completed correctly, you may need to do a CATCH block. The easiest way is probably to wrap RESOLVE_ALL in your own routine that has an ERROR keyword that returns whether the RESOLVE_ALL succeeded.
I'm not sure where I picked this up but you'll need two routines:
function validate_syntax_helper, routineName
compile_opt strictarr, hidden
catch, error
if (error ne 0) then return, 0
resolve_routine, routineName, /either, /compile_full_file
return, 1
end
and
function validate_syntax, routineName
compile_opt strictarr, hidden
oldquiet = !quiet
!quiet = 1
catch, error
if (error ne 0) then return, 0
; Get current directory
cd, current=pwd
o = obj_new('IDL_IDLBridge')
o->execute, '#' + pref_get('IDL_STARTUP')
; Change to current directory
o->execute, 'cd, ''' + pwd + ''''
; Validate syntax
cmd = 'result = validate_syntax_helper(''' + routineName + ''')'
o->execute, cmd
result = o->getVar('result')
obj_destroy, o
!quiet = oldquiet
return, result
end
You then call validate_syntax, which returns 1 when it can compile and 0 when it can't. I don't think this can be used from the IDL virtual machine since it uses execute, but maybe that doesn't matter to you. You'll have to manually run this on all your routines to be compiled instead of running resolve_all.
Related
I needed to write a solution to write data on and then print RFID labels en-masse, each generated as .png images from a template python script and data taken from a database or excel file.
To print the program simply calls the relative system utility (CUPS on unix systems) using subprocess.check_call(print_cmd) passing the image file (saved on a ram-mounted file system for minimal disk usage)
Now, it also needs to run on Windows systems, but there is not really a decent system utility for that, and solutions under a similar question command line tool for print picture? don't account for print-job completion or if the job results in an error, the margins are all screwed and the image is always rotated 90 degrees for some reason.
How can I sanely print an image using a command or a script in Windows and wait for it to complete successfully or return an error if the job results in an error?
Possibly with no dependencies
If you can install dependencies, there are many programs that offer a solution out-of-the-box.
The only sane way i could find to solve this issue with no dependencies is by creating a powershell script to account for this
[CmdletBinding()]
param (
[string] $file = $(throw "parameter is mandatory"),
[string] $printer = "EXACT PRINTER NAME HERE"
)
$ERR = "UserIntervention|Error|Jammed"
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
# https://stackoverflow.com/a/20402656/17350905
# only sends the print job to the printer
rundll32 C:\Windows\System32\shimgvw.dll,ImageView_PrintTo $file $printer
# wait until printer is in printing status
do {
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
Start-Sleep -Milliseconds 100
} until ( $status -eq "Printing" )
# wait until printing is done
do {
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
Start-Sleep -Milliseconds 100
} until ( $status -eq "Normal" )
I would then need to slightly modify the print subprocess call to
powershell -File "path\to\print.ps1" "C:\absolute\path\to\file.png"
Then there are a couple of necessary setup steps:
(discaimer, I don't use windows in english so i don't know how the english thigs are supposed to be called. i will use cursive for those)
create an example image, right click and then select Print
from the print dialog that opens then set up all the default options you want, like orientation, margins, paper type, etc etc for the specific printer you're gonna use.
Go to printer settings, under tools then edit Printer Status Monitoring
edit monitoring frequency to "only during print jobs". it should be disabled by default
in the next tab, modify polling frequency to the minimum available, 100ms during print jobs (you can use a lower one for the while not printing option
Assuming the following:
only your program is running this script
theres always only 1 printing job at a time for a given printer
the printer drivers were not written by a monkey and they actually report the current, correct printer status
This little hack will allow to print an image from a command and await job completion, with error management; and uses only windows preinstalled software
Further optimization could be done by keeping powershell subprocess active and only passing it scripts in the & "path\to\print.ps1" "C:\absolute\path\to\file.png" format, waiting for standard output to report an OK or a KO; but only if mass printing is required.
Having had to work on this again, just wanted to add a simpler solution in "pure" python using the pywin32 package
import time
import subprocess
from typing import List
try:
import win32print as wprint
PRINTERS: List[str] = [p[2] for p in wprint.EnumPrinters(wprint.PRINTER_ENUM_LOCAL)]
PRINTER_DEFAULT = wprint.GetDefaultPrinter()
WIN32_SUPPORTED = True
except:
print("[!!] an error occured while retrieving printers")
# you could throw an exception or whatever
# bla bla do other stuff
if "WIN32_SUPPORTED" in globals():
__printImg_win32(file, printer_name)
def __printImg_win32(file: str, printer: str = ""):
if not printer:
printer = PRINTER_DEFAULT
# verify prerequisites here
# i still do prefer to print calling rundll32 directly,
# because of the default printer settings shenaningans
# and also because i've reliably used it to spool millions of jobs
subprocess.check_call(
[
"C:\\Windows\\System32\\rundll32",
"C:\\Windows\\System32\\shimgvw.dll,ImageView_PrintTo",
file,
printer,
]
)
__monitorJob_win32(printer)
pass
def __monitorJob_win32(printer: str, timeout=16.0):
p = wprint.OpenPrinter(printer)
# wait for job to be sheduled
t0 = time.time()
while (time.time()-t0) < timeout:
ptrr = wprint.GetPrinter(p, 2)
# unsure about those flags, but definitively not errors.
# it seems they are "moving paper forward"
if ptrr["Status"] != 0 and ptrr["Status"] not in [1024,1048576]:
raise Error("Printer is in error (status %d)!" % ptrr["Status"])
if ptrr["cJobs"] > 0:
break
time.sleep(0.1)
else:
raise Error("Printer timeout sheduling job!")
# await job completion
t0 = time.time()
while (time.time()-t0) < timeout:
ptrr = wprint.GetPrinter(p, 2)
if ptrr["Status"] != 0 and ptrr["Status"] not in [1024,1048576]:
raise Error("Printer is in error (status %d)!" % ptrr["Status"])
if ptrr["cJobs"] == 0 and ptrr["Status"] == 0:
break
time.sleep(0.1)
else:
raise Error("Printer timeout waiting for completion!")
wprint.ClosePrinter(p)
return
useful additional resources
Print image files using python
Catch events from printer in Windows
pywin32's win32print "documentation"
This program is not complete but is a work in progress.
import speech_recognition as sr
import subprocess as sp
import time, os
r = sr.Recognizer()
print("Voice Recognition Software\n\n******************************************************************************\n")
while True:
r.energy_threshold = 8000
t = None
with sr.Microphone() as source:
success = False
print (">")
audio = r.listen(source)
try:
print("Processing...")
t = r.recognize_google(audio)
print (": " + t)
except sr.UnknownValueError:
print("Unknown input")
continue
except sr.RequestError as e:
print("An error occured at GAPI\nA common cause is lack of internet connection")
continue
if "open" in t:
t = t.replace("open","")
t = t.replace(" ","")
t = t + ".exe"
print (t)
for a,d,f in os.walk("C:\\"):
for files in f:
if files == t.lower() or files == t.capitalize() or files == t.upper():
pat = os.path.join(a,files)
print (pat)
sp.call([pat])
success = True
if success == True:
continue
The problem I'm facing is that after > or Processing the program sometimes stops responding. No error messages or anything, in the shell it just prints > or Processing and stays there.
This happens randomly, the program can function continuously for a long time but at any given moment for whatever reason it freezes. Usually after a minute or 2 it moves onto the next part and starts responding again but that isn't always the case.
I've attempted to create a sort of fail-safe so if it takes too long to respond the program closes and opens again but I was unsuccessful with that so now I'm trying to figure out the root cause of the problem.
Can someone with experience with this sort of thing help me understand why this is happening?
Edit:
I was able to solve the problem. Turns out there is a timeout parameter here r.listen(source).
I was able to solve the problem. Turns out there is a timeout parameter here r.listen(source).
Hello I am currently using IBM Spss, and I was wondering if there is a way when the code throws an exception to be able to obtain the line of code where the exception occurred? I am able to obtain the line number is there a way to access the stack of the lines that were executed and pull this information from there? Any ideas would be great Thank you in advance!
For Example:
Dim x, y, z
On Error Goto ErrorHandler
x = 30
y = 0
z = x / y 'would like to grab this code since this is where the error occurred
Exit
ErrorHandler:
debug.Log(Err.Description + _
" error occurred on line number " + _
CText(Err.LineNumber))
No, there is no way to map the line number to the actual code unless you keep your own index, allowing for macro expansion etc.
What you can do, though, is to submit the code in blocks and catch the exception for that block, which narrows down the location. In the limit, if each line is its own block, you will know exactly where the error occurred.
I use the Spyder IDE. Usually, when I am running non-parallelized scripts, I tend to debug using print statements. Depending on which statements are printed (or not), I can see where errors are occurring.
For example:
print "Started while loop..."
doWhileLoop = False
while doWhileLoop == True:
print "Doing something important!"
time.sleep(5)
print "Finished while loop..."
Above, I am missing a line that changes doWhileLoop to False at some point, so I will be stuck perpetually in the while loop, but my print statements let me see where it is in my code that I have hung up.
However, when running scripts that are parallelized, I get no output to the console until after the process has finished. Normally, what I do in this case is attempt to debug with a single process (i.e. temporarily deparallelize the program by running only one task, for instance), but currently, I am dealing with an error that seems to occur only when I am running more than one task.
So, I am having trouble figuring out what this error is using my usual methods -- how should I change my usual debugging practice in order to efficiently debug scripts employing multiprocessing?
Like #roippi said, debugging parallel things is hard. Another tool is using logging over print. Logging gives you severity, timestamps, and most importantly which process is doing something.
Example code:
import logging, multiprocessing, Queue
def myproc(arg):
return arg*2
def worker(inqueue, outqueue):
mylog = multiprocessing.get_logger()
mylog.info('start')
for job in iter(inqueue.get, 'STOP'):
mylog.info('got %s', job)
try:
outqueue.put( myproc(job), timeout=1 )
except Queue.Full:
mylog.error('queue full!')
mylog.info('done')
def executive(inqueue):
total = 0
mylog = multiprocessing.get_logger()
for num in iter(inqueue.get, 'STOP'):
total += num
mylog.info('got {}\ttotal{}', job, total)
logger = multiprocessing.log_to_stderr(
level=logging.INFO,
)
logger.info('setup')
inqueue, outqueue = multiprocessing.Queue(), multiprocessing.Queue()
if 0: # debug 'queue full!' issues
outqueue = multiprocessing.Queue(maxsize=1)
# prefill with 3 jobs
for num in range(3):
inqueue.put(num)
# signal end of jobs
inqueue.put('STOP')
worker_p = multiprocessing.Process(
target=worker, args=(inqueue, outqueue),
name='worker',
)
worker_p.start()
worker_p.join()
logger.info('done')
Example output:
[INFO/MainProcess] setup
[INFO/worker] child process calling self.run()
[INFO/worker] start
[INFO/worker] got 0
[INFO/worker] got 1
[INFO/worker] got 2
[INFO/worker] done
[INFO/worker] process shutting down
[INFO/worker] process exiting with exitcode 0
[INFO/MainProcess] done
[INFO/MainProcess] process shutting down
I'm trying to validate a path given in an inputdialog.
"a = path to file p.e. d:\mydoc.txt (but can be every file)
let a = inputdialog(docinput)
while 1
try
read (a)
catch /E484:/
echo "The file doesn't exist"
let a = inputdialog(docinput,a,"return")
if a == "return"
return
endif
endtry
endwhile
I want to check if the filename exists using the read command.
But it seems that read cannot read a variable.
read has to be something like this:
read d:\mydoc.txt
1) How can I read a variable?
If read gives an error message (E484 (cannot read the file)), the script has to return to the inputdialog.
I tried to do this with a try/endtry within a while/endwhile loop but I haven't found out how to break out of the loop.
2) How can I return the script to the inputdialog if the file doesn't exist?
You must use :execute to :read the filename contained in variable a:
execute "read " . a
:read is the wrong tool for the job, use filereadable() (or filewriteable(), depending on what you want to do with that file) instead:
if filereadable(expand(a))
" do something
else
" do something else
endif
I can't understand your second question.