I am new to Python so please excuse my rudimentary question.
When I get an error I can usually figure out what line caused the error, but sometimes from the error message itself I can't decide which line is responsible. So I add some messages between the lines to track the issue. Is there any more effective solution to that?
I am running my codes form ArcGIS toolbox script and I am not sure if I can trace the errors from there.
I always use print statements (okay, function in Py3). It's the most standard way. Just use it to track where are you now in your program, and what are you doing.
However, if your application processes a large data, or if it's a large application, print statements may be not enough. Sometimes, you'll need try and except statements, just to narrow the search of the error.
More on error handling? Here!
This may also be useful.
If youre trying to do this with a excepted error do this:
import traceback
import sys
try:
raise Exception("foo")
except:
for frame in traceback.extract_tb(sys.exc_info()[2]):
fname,lineno,fn,text = frame
print "Error in %s on line %d" % (fname, lineno)
otherwise just read the traceback
Related
i am trying to execute this very short code that took out from my bigger code because i was having problems with it. I was able to reproduce the problem (it gave the exact same error).
BACKGROUND INFO: i am just trying to get the first sentence out of this wikipedia search. but because the word i am searching for (kip, means chicken in Dutch) has a wide variety of meanings or something i get an error. i want to bypass this error using try: except: but it keeps displaying the error message anyway.
here is the code that just doesnt seem to work:
import wikipedia
wikipedia.set_lang('nl')
try:
summry = wikipedia.summary('kip', sentences=1)
print(summry + "\n")
except:
print("error")
i have tried replacing except: with this
except wikipedia.exceptions.DisambiguationError:
but it still doesnt work :( it always displays the error code regradless and prints "error" afterwards
/opt/virtualenvs/python3/lib/python3.8/site-packages/wikipedia/wikipedia.py:389:
GuessedAtParserWarning: No parser was explicitly specified, so I'm using the best available HTML
parser for this system ("html5lib"). This usually isn't a problem, but if you run this code on
another system, or in a different virtual environment, it may use a different parser and behave
differently.
The code that caused this warning is on line 389 of the file
/opt/virtualenvs/python3/lib/python3.8/site-packages/wikipedia/wikipedia.py. To get rid of this
warning, pass the additional argument 'features="html5lib"' to the BeautifulSoup constructor.
lis = BeautifulSoup(html).find_all('li')
error
i am using repl.it to program this
if anyone has any idea about why it keeps displaying the error anyway please please let me know :D
First of all, thank you all for commenting :D it helped a lot
At the end the solution that worked for me was inspired from Askold Ilvento's comment
although
with warnings.catch_warnings(): warnings.simplefilter("ignore")
didn't work when i adapted it a little bit it did the job!
this is the code that solved the problem and allowed me to ignore what was actually a warning (not an exception) and stop displaying it
import warnings
warnings.catch_warnings()
warnings.simplefilter("ignore")
i just added this at the start of the script and it solved the problem :D
once again all the credit for this code goes to Askold Ilvento i just had to add a little bit to it to make it work
A parser I created reads recorded chess games from a file. The API is used like this:
import chess.pgn
pgn_file = open("games.pgn")
first_game = chess.pgn.read_game(pgn_file)
second_game = chess.pgn.read_game(pgn_file)
# ...
Sometimes illegal moves (or other problems) are encountered. What is a good Pythonic way to handle them?
Raising exceptions as soon as the error is encountered. However, this makes every problem fatal, in that execution stops. Often, there is still useful data that has been parsed and could be returned. Also, you can not simply continue parsing the next data set, because we are still in the middle of some half-read data.
Accumulating exceptions and raising them at the end of the game. This makes the error fatal again, but at least you can catch it and continue parsing the next game.
Introduce an optional argument like this:
game = chess.pgn.read_game(pgn_file, parser_info)
if parser_info.error:
# This appears to be quite verbose.
# Now you can at least make the best of the sucessfully parsed parts.
# ...
Are some of these or other methods used in the wild?
The most Pythonic way is the logging module. It has been mentioned in comments but unfortunately without stressing this hard enough. There are many reasons it's preferable to warnings:
Warnings module is intended to report warnings about potential code issues, not bad user data.
First reason is actually enough. :-)
Logging module provides adjustable message severity: not only warnings, but anything from debug messages to critical errors can be reported.
You can fully control output of logging module. Messages can be filtered by their source, contents and severity, formatted in any way you wish, sent to different output targets (console, pipes, files, memory etc)...
Logging module separates actual error/warning/message reporting and output: your code can generate messages of appropriate type and doesn't have to bother how they're presented to end user.
Logging module is the de-facto standard for Python code. Everyone everywhere is using it. So if your code is using it, combining it with 3rd party code (which is likely using logging too) will be a breeze. Well, maybe something stronger than breeze, but definitely not a category 5 hurricane. :-)
A basic use case for logging module would look like:
import logging
logger = logging.getLogger(__name__) # module-level logger
# (tons of code)
logger.warning('illegal move: %s in file %s', move, file_name)
# (more tons of code)
This will print messages like:
WARNING:chess_parser:illegal move: a2-b7 in file parties.pgn
(assuming your module is named chess_parser.py)
The most important thing is that you don't need to do anything else in your parser module. You declare that you're using logging system, you're using a logger with a specific name (same as your parser module name in this example) and you're sending warning-level messages to it. Your module doesn't have to know how these messages are processed, formatted and reported to user. Or if they're reported at all. For example, you can configure logging module (usually at the very start of your program) to use a different format and dump it to file:
logging.basicConfig(filename = 'parser.log', format = '%(name)s [%(levelname)s] %(message)s')
And suddenly, without any changes to your module code, your warning messages are saved to a file with a different format instead of being printed to screen:
chess_parser [WARNING] illegal move: a2-b7 in file parties.pgn
Or you can suppress warnings if you wish:
logging.basicConfig(level = logging.ERROR)
And your module's warnings will be ignored completely, while any ERROR or higher-level messages from your module will still be processed.
Actually, those are fatal errors -- at least, as far as being able to reproduce a correct game; on the other hand, maybe the player actually did make the illegal move and nobody noticed at the time (which would make it a warning, not a fatal error).
Given the possibility of both fatal errors (file is corrupted) and warnings (an illegal move was made, but subsequent moves show consistency with that move (in other words, user error and nobody caught it at the time)) I recommend a combination of the first and second options:
raise an exception when continued parsing isn't an option
collect any errors/warnings that don't preclude further parsing until the end
If you don't encounter a fatal error then you can return the game, plus any warnings/non-fatal errors, at the end:
return game, warnings, errors
But what if you do hit a fatal error?
No problem: create a custom exception to which you can attach the usable portion of the game and any other warnings/non-fatal errors to:
raise ParsingError(
'error explanation here',
game=game,
warnings=warnings,
errors=errors,
)
then when you catch the error you can access the recoverable portion of the game, along with the warnings and errors.
The custom error might be:
class ParsingError(Exception):
def __init__(self, msg, game, warnings, errors):
super().__init__(msg)
self.game = game
self.warnings = warnings
self.errors = errors
and in use:
try:
first_game, warnings, errors = chess.pgn.read_game(pgn_file)
except chess.pgn.ParsingError as err:
first_game = err.game
warnings = err.warnings
errors = err.errors
# whatever else you want to do to handle the exception
This is similar to how the subprocess module handles errors.
For the ability to retrieve and parse subsequent games after a game fatal error I would suggest a change in your API:
have a game iterator that simply returns the raw data for each game (it only has to know how to tell when one game ends and the next begins)
have the parser take that raw game data and parse it (so it's no longer in charge of where in the file you happen to be)
This way if you have a five-game file and game two dies, you can still attempt to parse games 3, 4, and 5.
I offered the bounty because I'd like to know if this is really the best way to do it. However, I'm also writing a parser and so I need this functionality, and this is what I've come up with.
The warnings module is exactly what you want.
What turned me away from it at first was that every example warning used in the docs looks like these:
Traceback (most recent call last):
File "warnings_warn_raise.py", line 15, in <module>
warnings.warn('This is a warning message')
UserWarning: This is a warning message
...which is undesirable because I don't want it to be a UserWarning, I want my own custom warning name.
Here's the solution to that:
import warnings
class AmbiguousStatementWarning(Warning):
pass
def x():
warnings.warn("unable to parse statement syntax",
AmbiguousStatementWarning, stacklevel=3)
print("after warning")
def x_caller():
x()
x_caller()
which gives:
$ python3 warntest.py
warntest.py:12: AmbiguousStatementWarning: unable to parse statement syntax
x_caller()
after warning
I'm not sure if the solution is pythonic or not, but I use it rather often with slight modifications: a parser does its job within a generator and yields results and a status code. The receiving code makes decisions what to to with failed items:
def process_items(items)
for item in items:
try:
#process item
yield processed_item, None
except StandardError, err:
yield None, (SOME_ERROR_CODE, str(err), item)
for processed, err in process_items(items):
if err:
# process and log err, collect failed items, etc.
continue
# further process processed
A more general approach is to practice in using design patterns. A simplified version of Observer (when you register callbacks for specific errors) or a kind of Visitor (where the visitor has methods for procesing specific errors, see SAX parser for insights) might be a clear and well understood solution.
Without libraries, it is difficult to do this cleanly, but still possible.
There are different methods of handling this, depending on the situation.
Method 1:
Put all contents of while loop inside the following:
while 1:
try:
#codecodecode
except Exception as detail:
print detail
Method 2:
Same as Method 1, except having multiple try/except thingies, so it doesn't skip too much code & you know the exact location of the error.
Sorry, in a rush, hope this helps!
I created a script that connects via python-xmpp (xmpppy) to chat.euw1.lol.riotgames.com, but I get always an error, even there is none.
Here is the code:
jid=xmpp.protocol.JID('my_jid#pvp.net')
cl=xmpp.Client(jid.getDomain(),debug=[])
con=cl.connect(server=('chat.euw1.lol.riotgames.com', 5223))
if not con:
print 'could not connect!'
Again: everything works fine, but I still get this nasty error message:
An error occurred while looking up _xmpp-client._tcp.chat.euw1.lol.riotgames.com
I just wonder how I can prevent xmpppy from outputting it, I have tried several techniques like setting sys.stdout/stderr to os.devnull.
I think you can use a try/except structure to handle that problem..
try:
jid=xmpp.protocol.JID('my_jid#pvp.net')
cl=xmpp.Client(jid.getDomain(),debug=[])
con=cl.connect(server=('chat.euw1.lol.riotgames.com', 5223))
except:
print 'could not connect!'
I was looking to possibly try and save a traceback object and somehow pickle it to a file that I can access. An example of a use case for this is if I am submitting some python code to a farm computer to run and it fails, it would be nice to be able to open a session and access that traceback to debug the problem rather than just seeing a log of the traceback. I do not know if there is any sort of way to do this but thought it would be worth asking why it couldn't if so.
okay so you can use traceback.print_exception(type, value, traceback[, limit[, file]]) and save it in a text or json or you can refer to docs
if you find it helpful please mark it correct or upvote thanx..:)
Depending on how you've written your code, the try statement is probably your best answer. Since any error is just a class that inherits Python's builtin Exception, you can raise custom errors everywhere you need more information about a thrown error. You just need to rename your errors or pass in an appropriate string as the first argument. If you then try your code and use the except statement except CustomError as e, you can pull all the information you want out of e in the except statement as a regular instance. Example:
Your code would be:
def script():
try: codeblock
except Exception as e: raise Error1('You hit %s error in the first block'% e)
try: codeblock 2
except Exception as e: raise Error2('You hit %s error in the second block' % e)
try: script()
except Exception as e:
with open('path\to\file.txt','w') as outFile:
outFile.write(e)
The last part is really nothing more than creating your own log file, but you have to write it down somewhere, right?
As for using the traceback module mentioned above, you can get error information out of that. Any of the commands here can get you a list of tracebacks:
http://docs.python.org/2/library/traceback.html
On the otherhand, if you're trying to avoid looking at log files, the traceback module is only going to give you the same thing a log file would, in a different format. Adding your own error statements in your code gives you more information than a cryptic ValueError about what actually happened. If you print the traceback to your special error, it might give you still more information on your issue.
I'm trying to write to a file but it's not working. I've gone through step-by-step with the debugger (it goes to the write command but when I open the file it's empty).
My question is either: "How do I see what the error is so I can debug?", "What can go wrong when trying to write to a file that would cause it to behave this way?".
sqlScript = open('script-file.sql', 'a')
try:
sqlScript.write(sqlLine)
except IOError as (errno, strerror):
print "I/O error({0}): {1}".format(errno, strerror)
This should be simple but I can't seem to find an answer. Also, I apologize in advance as English is a second language.
Edit: I put a print statement just before and the string is not empty.
Edit2: I'm using python 2.6 if that factors in somehow.
Edit 3: I've found a "solution" to my error. I decided to try and run my script using IDLE instead of PyCharm and it works like a charm (pun intended). I have no clue why, but there it is. Any reason why that would happen?!
Building on Chris Morris' answer, maybe do something like this:
try:
sqlScript.write(sqlLine)
except Exception as e:
print type(e)
print str(e)
This will catch any Exception thrown (provided it's a subclass of Exception, of course) and tell you the type and the error message.
Also, it's possible to define multiple except: cases for different possible exceptions, so maybe try doing that for each exception that might be potentially thrown/raised.
The following code allows you to see what exception it is that is being thrown, and see a trace of where it originated from.
try:
sqlScript.write(sqlLine)
except:
print "Unexpected error:", sys.exc_info()[0]
raise
See http://docs.python.org/tutorial/errors.html for more info.
You have to put your cursor at the beginning of the file. You can do that with seek method:
myScript.seek(0)
See this answer: https://stackoverflow.com/a/2949648/2119117
If no exception is being tossed, I'd suspect the string variable 'sqlLine' is empty.
Did you print it before the write statement?
Are the keywords in the script in lowercase? The same thing happened to me in another db and I solved it by changing words to UPPERCASE.
Your current working directory isn't what you expect it to be and it's successfully writing to some script-file.sql in another directory. Try printing os.getcwd() and make sure it's what you expect, and look in that directory.
It happened on my linux environment but work on windows try
sqlScript = open('script-file.sql', 'a', buffering=False)
or
sqlScript = open('script-file.sql', 'a', 0)