问题
I am new to the stackoverflow community, and new to programming in general. One of my first projects is to build a web scraper to see if I can collect market data. In attempting to build this, I keep getting stuck with an unbound local error. I am aware that this has something to do with how I am instantiating my class and how I am referencing the variable,strong text but not sure how to trouble shoot it..
class Stock:
def __init__(self,symbol,company):
self.symbol = symbol
self.company = company
self.data = []
def query_stock_symbol(self):
wait_time = round(max(5, 10 +random.gauss(0,3)), 2)
time.sleep(wait_time)
url = 'https://www.barrons.com/quote/stock/us/xnys/%s?mod=DNH_S' % (self.symbol)
page = requests.get(url)
if page.status_code == 403 or page.status_code == 404:
url = 'https://www.barrons.com/quote/stock/us/xnas/%s?mod=DNH_S' % (self.symbol)
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
headers = {'User-Agent': user_agent}
req = urllib.request.Request(url,headers=headers)
try:
response = urllib.request.urlopen(req)
except urllib.error.URLError as e:
print(e.reason)
self.soup = BeautifulSoup(response, 'html.parser')
# Finding stock price
for a in self.soup.findAll('span',{'class':'market_price'}):
stock_price_str = a.text.replace(',','')
if stock_price_str != 'N/A':
self.stock_price = float(stock_price_str)
else:
self.stock_price = None
The error I receive is such
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-277-f9c756bf109f> in <module>
1 x = Stock('CRM','Salesforce')
----> 2 x.query_stock_symbol()
3
<ipython-input-276-1f910b91d713> in query_stock_symbol(self)
26 print(e.reason)
27
---> 28 self.soup = BeautifulSoup(response, 'html.parser')
29
30
UnboundLocalError: local variable 'response' referenced before assignment
```
Thanks for all your time and consideration, I really do appreciate it
回答1:
That is because you have response
declared in a try
block while you attempt to use it outside of that block, you could either:
1- declare response
globally before using it inside the try
block, like this:
try:
global response
response = ...
except ...:
...
self.soup = ....
2- instantiate the Soup
object inside the try
block below the response
assignment like this:
try:
response = ...
self.soup = BeautifulSoup(response, 'html.parser')
or
3- declare the response
variable before the try
block, this is a more problematic approach and could lead to problems when response is not assigned correctly (like when the exception
is raised), however if you decide to go with this, you could do something like this:
response = None
try:
response = ...
except ...:
.....
self.soup = ...
Always remember that locally declared variables, like in a try
block, an if
block, an else
block, etc. are not accessible outside of said block, they are local to that block
回答2:
You should handle the error raised by urllib.request.urlopen
: if this method raises an error you only print it and keep on executing your code. But, this means that all the instructions in the try block could have not been executed and that response
has not defined.
For example, this code works as expected:
try:
a = 10
except Exception:
print(e)
print(a)
The output is:
10
so the variable a
is defined when you print it; on the other hand, this code raises an error like the one you are experimenting:
try:
a = 10 / 0
except Exception as e:
print(e)
print(a)
division by zero
Traceback (most recent call last):
File "try_catch_example.py", line 6, in <module>
print(a)
NameError: name 'a' is not defined
So, the real problem is that you have to decide what to do when something in the try
block fails.
In your case, printing the error is not enough; you should, probably, interrupt the method, raising a warning or reraising a more 'commented' error:
try:
response = urllib.request.urlopen(req)
except urllib.error.URLError as e:
print('Something wrong with urlopen! Read carefully the reason of the error')
print(f'req: {req}')
print(e.reason)
raise RuntimeError('Failed to open the required url') from exc
来源:https://stackoverflow.com/questions/65636186/error-local-variable-has-been-referenced-before-assignment