Error local variable has been referenced before assignment

喜欢而已 提交于 2021-02-11 12:32:20

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!