It is a scoping thing, or rather, the lack of a scope. Python does not have block scopes; the only thing that defines a new scope in Python is a function definition. (Comprehensions do, too, but that's because they are implemented using anonymous functions.)
There is no "local" x in either the try block or the except block; both are the same x as defined before the try statement.
One exception: e is kind of local. It's still in the same scope as x, but it is unset by the try statement once it completes to avoid a reference cycle, just as if you had written del e immediately after the statement.
assign a global variable in try/except
Scope of a variable
Python variable scope within try/except blocks - Stack Overflow
Does this try/except behaviour make any sense?
try statements do not create a new scope, but text won't be set if the call to url lib.request.urlopen raises the exception. You probably want the print(text) line in an else clause, so that it is only executed when there is no exception.
try:
url = "http://www.google.com"
page = urllib.request.urlopen(url)
text = page.read().decode('utf8')
except (ValueError, RuntimeError, TypeError, NameError):
print("Unable to process your request dude!!")
else:
print(text)
If text needs to be used later, you really need to think about what its value is supposed to be if the assignment to page fails and you can't call page.read(). You can give it an initial value prior to the try statement:
text = 'something'
try:
url = "http://www.google.com"
page = urllib.request.urlopen(url)
text = page.read().decode('utf8')
except (ValueError, RuntimeError, TypeError, NameError):
print("Unable to process your request dude!!")
print(text)
or in the else clause:
try:
url = "http://www.google.com"
page = urllib.request.urlopen(url)
text = page.read().decode('utf8')
except (ValueError, RuntimeError, TypeError, NameError):
print("Unable to process your request dude!!")
else:
text = 'something'
print(text)
As answered before there is no new scope introduced by using try except clause, so if no exception occurs you should see your variable in locals list and it should be accessible in current (in your case global) scope.
print(locals())
In module scope (your case) locals() == globals()
Hej guys. I have a problem assign a global variable inside a try/except. The try/except is in the main function and iam using the variable in another function. when i print the variable outside the main function i get "something" instead of the assigned value. how can i solve it?
company ="something" #global variable
try:
loggInThisFile = open(reportFilePath,'w')
except Exception as e:
print("can't create report file:", reportFilePath)
else:
company = link.split(" ; ")[1]
print(company) #prints assigned value
ps: the declaration and assignation is done before it soposed to be used.
Thanks in advance
the one line you call fails, which means that process is never bound (because the code never makes it that far!). so there's no way to do that.
in other words, when you call subprocess.Popen an exception is raised, so there's no result to set process to.
If an exception is raised, a process may not be created. Hence you can't assume the variable process will exist within the except block.
Dear Pythonistas, I am getting more experience using try/except but I have a situation where Python appears to behave weirdly IMO.
My (a bit complex) code where I work with connection errors can be reduced to an equivalent small example:
try:
1 / 0
except ZeroDivisionError as error:
try:
[1, 2, 3][3]
except IndexError as error:
pass
print("The last error was:", error)
Wouldn't you also expect it to print the index error? It doesn't! Instead, a NameError for the variable error is thrown. Does anybody understand why?
I have a few more details on a Stack Overflow post where you are welcome to answer if you are looking for reputation in there:
https://stackoverflow.com/questions/75473452/why-is-python-throwing-a-nameerror-when-doing-nested-exceptions-with-same-variab
I have some code that pulls stock information into an excel sheet using the tickers present in the excel file, and I recently am trying to expand this code to pull in the stocks sectors using yfinance. The issue is that some of my tickers are EFT's, which do not have sectors. So whenever my code tries to run, it will throw a syntax error when it reaches an EFT stock. If I take out all the EFT's, it runs just fine.
What I'm trying to do is set my variable (sector) as a try/exception block, but I don't know if this is possible. Could someone please help me out on this? Examples or suggestions? I'm not exactly new to Python, but I'm not a regular program either. Just really lost and in hard core struggle mode on this one.
Excerpt from my code below, along with what I'm having trouble with developing below that.
import xlwings as xw
from yahoofinancials import YahooFinancials
import pandas as pd
import yfinance as yf
def main():
wb = xw.Book.caller()
sheet = wb.sheets[0]
df = pd.DataFrame()
tickers = sheet.range("D7").options(expand='down').value
for ticker in tickers:
find_sector = yf.Ticker(ticker)
sector = find_sector.info['sector']
new_row = {
"GICS Sector": sector,
}
df = df.append(new_row, ignore_index=True)
sheet.range("E6").options(index=False).value = df
if __name__ == "__main__":
xw.Book("dividends.xlsm").set_mock_caller()
main()What I'm envisioning/trying/struggling with for setting my 'sector' variable:
sector =
try:
find_sector.info['sector']
else:
print('EFT')Add the line global foobar to the top of get_foobar()
This tells the bytecode compiler you want to reference the variable in this function using global scope instead of local.
Assignment implicitly changes a variable's scope to local for the whole function scope.
In bytecode:
## code input (local)
def test():
print foobar
foobar = 2
## bytecode output
#
# 3 0 LOAD_FAST 0 (foobar)
# 3 PRINT_ITEM
# 4 PRINT_NEWLINE
#
# 4 5 LOAD_CONST 1 (2)
# 8 STORE_FAST 0 (foobar)
# 11 LOAD_CONST 0 (None)
# 14 RETURN_VALUE
## code input (global)
def test():
global foobar
print foobar
foobar = 2
## bytecode output
#
# 4 0 LOAD_GLOBAL 0 (foobar)
# 3 PRINT_ITEM
# 4 PRINT_NEWLINE
#
# 5 5 LOAD_CONST 1 (2)
# 8 STORE_GLOBAL 0 (foobar)
# 11 LOAD_CONST 0 (None)
# 14 RETURN_VALUE
Notice the usage of LOAD_FAST and STORE_FAST instead of LOAD_GLOBAL and STORE_GLOBAL. The Python dis module documentation has a list of opcodes for reference.
You can use this code to quickly dump the bytecode for a function:
import compiler, dis
code = compiler.compile('''
def test():
print foobar
foobar = 2
''', '__main__', 'exec')
dis.dis(code.co_consts[1])
Martijn Pieters called it. Because you made an assignment to foobar inside the function, a new, local variable foobar was created, but this happens at compile time not runtime, which is why an uninitialized version of foobar is already existing inside your try block.
What's wrong with the "else" clause ?
for filename in files:
try:
im = Image.open(os.path.join(dirname,filename))
except IOError, e:
print "error opening file :: %s : %s" % (os.path.join(dirname,filename), e)
else:
print im.size
Now since you're in a loop, you can also use a "continue" statement:
for filename in files:
try:
im = Image.open(os.path.join(dirname,filename))
except IOError, e:
print "error opening file :: %s : %s" % (os.path.join(dirname,filename), e)
continue
print im.size
If you can't open the file as an image, and only want to work on valid images, then include a continue statement in your except block which will take you to the next iteration of your for loop.
try:
im = Image.open(os.path.join(dirname, filename))
except IOError:
print 'error opening file :: ' + os.path.join(dirname, filename)
continue
Simple: while does not create a scope in Python. Python has only the following scopes:
- function scope (may include closure variables)
- class scope (only while the class is being defined)
- global (module) scope
- comprehension/generator expression scope
So when you leave the while loop, e, being a local variable (if the loop is in a function) or a global variable (if not), is still available.
tl;dr: Python is not C.
in except ... as e, the e will be drop when Jump out of try except, Whether or not it was defined before.
When an exception has been assigned using as target, it is cleared at the end of the except clause.
refer to offical website link: https://docs.python.org/3/reference/compound_stmts.html#the-try-statement
Python does not have block scope. Anything defined inside the try block will be available outside.
That said, you would still have a problem: if it is the getConnection() call that raises the error, cursor will be undefined, so the reference in the finally block will error.
I'd suggest using contexts, like:
from contextlib import closing
try:
with closing(getConnection(database)) as connection:
with closing(connection.cursor()) as cursor:
cursor.execute("some query")
except:
log.error("Problem")
raise
This should ensure the closing (see more here).
In some cases, you won't even need closing since connection is most likely to support the context protocol itself, so that would be just with getConnection(database)...