This question already has answers here:
Dismiss PyCharm code inspection warning for particular line of code
(2 answers)
Closed 5 months ago.
I am reading in some data with try, except blocks (to allow for managed shutdown in case of errors), this often causes Pycharm to read variables as "may be referenced before assignment" as it is apparently incapable of working out that they will either have a value or the function will be exited.
e.g.
import sys
def program_exit(code):
sys.exit(code)
def read_a(input_value):
try:
a = input_value
except:
program_exit(5)
a += 1 # referenced before assignment warning
return a
I know it is possible to block the warning for a specific line but is there any way to tell pycharm that the variable will be defined so that I don't have to block the warning for all subsequent uses of the variable
e.g.
import sys
def program_exit(code):
sys.exit(code)
def read_a(input_value):
try:
a = input_value
except:
program_exit(5)
# Pycharm: has_value(a)
a += 1 # no warning
return a
Thanks
This warning is correct, because in the try block can occur an exception, and the variable can be not defined. I see two ways of solving it:
Defining the variable: You can define the variable as None before the try/catch, so no matter what happens, the variable will always exist.
import sys
def program_exit(code):
sys.exit(code)
def read_a(input_value):
a = None
try:
a = input_value
except:
program_exit(5)
a += 1
return a
Return in the except: PyCharm does not understand that the program_exit function kills the program, but you can add a return after it, the result will be the same, but PyCharm will understand that the except block stops function execution.
import sys
def program_exit(code):
sys.exit(code)
def read_a(input_value):
try:
a = input_value
except:
program_exit(5)
return
a += 1
return a
Related
I have below script which generates report for large size data.
Due to large size data request call times out.
I have added exception to handle this situation which works fine to get keep script running.
Issue I am having is after exception it goes to next project and skips the projects where it timed out.
I want it to start from same project again.
How can I achieve this ?
if __name__ = ‘__main__’
for project in AllProjectData['value']:
try:
project_name = project['name']
** code to be executed
except:
requests.ConnectionError,
requests.exceptions.ReadTimeout,
requests.exceptions.Timeout,
requests.exceptions.ConnectTimeout
continue
You are catching exceptions in a very odd way. I've never seen it done like this. I believe this code is catching all exceptions. For example:
try:
1/0
except:
ZeroDivisionError
pass
Works fine, but so does (it should raise IndexError):
try:
a = []
print(a[1])
except:
ZeroDivisionError
pass
So you shouldn't write except statements this way. What you should have is something along the lines:
success = False
while not success:
try:
# Your execution code
except (requests.ConnectionError,
requests.exceptions.ReadTimeout,
requests.exceptions.Timeout,
requests.exceptions.ConnectTimeout):
continue
else:
success = True
Also you should try and not put so much code in your except statement as it is confusing as to what you're trying to catch and where. Also, you're completely missing some possibilities like a KeyError when there's no id field in project and others.
Try this -
def myfunc():
# Write the code given in question completely
# Then add this in your except statement
except:
requests.ConnectionError,
requests.exceptions.ReadTimeout,
requests.exceptions.Timeout,
requests.exceptions.ConnectTimeout
# Call your function so that it will jump back to the same function
myfunc()
# You don't need continue keyword because it jumps to the same function
The simplest way would be to use a while loop with a counter variable. Let me demonstrate:
i = 0
while i < len(AllProjectData['value']):
try:
project = AllProjectData['value'][i]
# code to be executed
i += 1 # increment counter on success
except:
requests.ConnectionError,
requests.exceptions.ReadTimeout,
requests.exceptions.Timeout,
requests.exceptions.ConnectTimeout
continue
This way, you will go to the next project only if work on the previous project was executed, as the loop variable is incremented only in the try block.
Note: I have assumed that your iterable is indexable. If it's not, just pass it inside the list() constructor.
What is the best practice to run functions in sequence?
I have 4 functions, if the previous one failed, do not run the following ones. In each function, I set global error and error = 1 when exception occurs. Then in main, I just use if statement to check the value of error. I think there should be a better way to do it.
def main():
engine = conn_engine()
if error == 0:
process_sql()
if error == 0:
append_new_rows_to_prod()
if error == 0:
send_email_log()
The canonical way is to raise an exception within the function. For example:
def process_sql():
# Do stuff
if stuff_failed:
raise ProcessSQLException("Error while processing SQL")
def append_new_rows_to_prod():
# Do other stuff
if other_stuff_failed:
raise AppendRowsException("Error while appending rows")
def main():
engine = conn_engine()
try:
process_sql()
append_new_rows_to_prod()
send_email_log()
except ProcessSQLException, AppendRowsException as e:
# Handle exception, or gracefully exit
I must be missing something as PyCharm is reporting a variable is unused but it is in fact used on the very next line.
Any idea why PyCharm reports this way? Is it a bug or did I do something that needs to be changed?
Code:
def start_mass_reassign(self):
try:
or_dns = cx_Oracle.makedsn('REDACTED', REDACTED, service_name='REDACTED')
con = cx_Oracle.connect(user=self.username.get(), password=self.password.get(), dsn=or_dns)
valid_login = True
except cx_Oracle.DatabaseError as e:
if 'invalid username/password' in str(e).lower():
print('Invalid login')
valid_login = False
else:
valid_login = False
raise
if valid_login:
# rest of code verified works fine.
Image of notification reported by PyCharm.
As suggested by lmiguelvargasf I did try to use different values but it did not get rid of the error.
You are getting an error because in the else branch, you are raising an exception, and that variable will never be used because the flow execution terminates when the exception is raised.
I have the strangest problem I have ever met in my life.
I have a part of my code that looks like this:
class AzureDevOpsServiceError(Exception):
pass
skip = ["auto"]
def retrieve_results():
print(variable_not_defined)
... # some useful implementation
if not "results" in skip:
try:
print("before")
retrieve_results()
print("after")
except AzureDevOpsServiceError as e:
print(f"Error raised: {e}")
Obviously, this shall raise an error because variable_not_defined is, well, not defined.
However, for some strange reasons, the code executes correctly and prints
before
after
I have tried to call the function with an argument (retrieve_results(1234)) or adding an argument in the function (def retrieve_results(arg1) and retrieve_results()): both modifications will trigger an exception, so obviously the function is called.
Anyone has got a similar issue and knows what happens?
FYI: this is actually what my implementation looks like:
from azure.devops.exceptions import AzureDevOpsServiceError
import logging
def _retrieve_manual_results(connect: Connectivity, data: DataForPickle) -> None:
"""Retrieve the list of Test Results"""
print("G" + ggggggggggggggggggggggggggggggggggggg)
logger = connect.logger
data.run_in_progress = [165644]
if __name__ == "__main__":
p = ...
connect = ...
data = ...
if not "results" in p.options.skip:
try:
print("........B.........")
_retrieve_manual_results(connect, data)
print("........A.........")
except AzureDevOpsServiceError as e:
logging.error(f"E004: Error while retrieving Test Results: {e}")
logging.debug("More details below...", exc_info=True)
As highlighted by #gmds, it was a problem of cache.
Deleting the .pyc file didn't do much.
However, I have found a solution:
Renaming the function (e.g. adding _)
Running the program
Renaming back (i.e. removing _ in the previous example)
Now, the issue is solved.
If anyone knows what is going behind the scene I am very interested.
Given the following simple example:
while True:
readme = input("Write here something:")
if readme == "":
raise Exception("That was empty!")
(1) How can the main code / loop continue to work after an Exception has been thrown? (2) And if we simultaneously run another thread, how can we catch the Exception in there?
Edit: is it possible to do this without having a try/except block inside the loop?
Without using the try/catch it is not possible in python. When we call a function in python and it raises a exception, the exceptions is propagated to the caller function and it continues.
If you do not handle the the exception anywhere in the above chain, interpreter just throw it out to the user.
Yes it is possible with try/except.
Try making a function like so:
from inspect import currentframe,getframeinfo
def Raise(ex):
cf = currentframe()
#Get the line
line=cf.f_back.f_lineno
print('Traceback:\n'+ex+'\nin line '+str(line))
wait=input('Press Enter to continue excecution.')
And then call:
myexception('That was empty!)
For example (from the example):
from inspect import currentframe,getframeinfo
def Raise(ex):
cf = currentframe()
#Get the line
line=cf.f_back.f_lineno
print('Traceback:\n'+ex+'\nin line '+str(line))
wait=input('Press Enter to continue excecution.')
readme = input("Write here something:")
if readme == "":
Raise("That was empty!")