Repository: ranaroussi/yfinance

Issue:
AttributeError: 'float' object has no attribute 'upper'
Any ideas on the error below?

My code works fine on windows locally on my laptop, it basically pulls data for a group of 5000 stocks 1 by 1. When i try to run it onlinus most of the symbols work fine, but i seem to get this error a handfull of times during the loop.

Any ideas what might be causing it, i already have it wrapped in a try/except ststement but the error weirdly still shows (and the code continues if i use ctrl+c)

Any help appreciated. 

Exception in thread Thread-1337:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.8/dist-packages/multitasking/__init__.py", line 104, in _run_via_pool
    return callee(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/yfinance/multi.py", line 191, in _download_one_threaded
    data = _download_one(ticker, start, end, auto_adjust, back_adjust,
  File "/usr/local/lib/python3.8/dist-packages/yfinance/multi.py", line 205, in _download_one
    return Ticker(ticker).history(period=period, interval=interval,
  File "/usr/local/lib/python3.8/dist-packages/yfinance/base.py", line 168, in history
    end = utils._parse_user_dt(end, tz)
  File "/usr/local/lib/python3.8/dist-packages/yfinance/utils.py", line 154, in _parse_user_dt
    dt = _tz.timezone(exchange_tz).localize(dt)
  File "/usr/local/lib/python3.8/dist-packages/pytz/__init__.py", line 170, in timezone
    if zone.upper() == 'UTC':
AttributeError: 'float' object has no attribute 'upper'


Discussion:
This will be related to my recent timezone changes, but I need your help to debug. I figure it's related to either the spam, or the threading.

1. I've added some debug code to branch 'debug/tz-is-float'. Can you switch to it and tell me if you see any error messages like this?
> Exception: Ticker('AMZN').info['exchangeTimezoneName'] = '0' (<class 'int'>) but should be str

2. I've also added a potential fix - In yfinance/utils.py bottom uncomment the two lines containing 'cache_mutex' - does that fix problem?
i dont see any commented lines in utils.py
Exception in thread Thread-1130:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.8/dist-packages/multitasking/__init__.py", line 104, in _run_via_pool
    return callee(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/yfinance/multi.py", line 199, in _download_one_threaded
    data = _download_one(ticker, start, end, auto_adjust, back_adjust,
  File "/usr/local/lib/python3.8/dist-packages/yfinance/multi.py", line 213, in _download_one
    return Ticker(ticker).history(period=period, interval=interval,
  File "/usr/local/lib/python3.8/dist-packages/yfinance/base.py", line 168, in history
    end = utils._parse_user_dt(end, tz)
  File "/usr/local/lib/python3.8/dist-packages/yfinance/utils.py", line 154, in _parse_user_dt
    dt = _tz.timezone(exchange_tz).localize(dt)
  File "/usr/local/lib/python3.8/dist-packages/pytz/__init__.py", line 170, in timezone
    if zone.upper() == 'UTC':
AttributeError: 'float' object has no attribute 'upper'
i unistalled and re installed... looks like same error
not sure how i switch to branch 'debug/tz-is-float'

I meant a GitHub branch, not PIP. Read this: https://github.com/ranaroussi/yfinance/discussions/1080
ok loaded new files from git and found those cache lines to uncomment. re running now
Exception in thread Thread-1130:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.8/dist-packages/multitasking/__init__.py", line 104, in _run_via_pool
    return callee(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/yfinance/multi.py", line 199, in _download_one_threaded
    data = _download_one(ticker, start, end, auto_adjust, back_adjust,
  File "/usr/local/lib/python3.8/dist-packages/yfinance/multi.py", line 213, in _download_one
    return Ticker(ticker).history(period=period, interval=interval,
  File "/usr/local/lib/python3.8/dist-packages/yfinance/base.py", line 154, in history
    tz = self._get_ticker_tz()
  File "/usr/local/lib/python3.8/dist-packages/yfinance/base.py", line 345, in _get_ticker_tz
    raise Exception("Ticker('{}') cached tz = '{}' ({}) but should be str".format(self.ticker, tkr_tz, type(tkr_tz)))
Exception: Ticker('BRK.B') cached tz = 'nan' (<class 'float'>) but should be str
so it looks like its the symbols

even on my laptop BRK.B fails, but my code handles it, whereas on linux it throws an error still, not sure understand that...

try:
        yf.pdr_override()
        data = pdr.get_data_yahoo(x, start=start_date, end=end_date)
        adj = data['Adj Close']
        adj14 = adj.tail(n=14)
        bb_low(adj14,1)
except:

ive run that command and re running now.

really appreciate the help and support, cant thank you enough for your work on this.
Ticker 'BRK.B' doesn't actually exist, so this is about yfinance handling problems in nice way. I've pushed an update that should solve.

yfinance has a local cache now for storing timezones. If cache different between machines then different behaviour.
as in a new version via pip?
No to the GitHub branch. I can't push to PIP until you confirm fix.
ok will download again and re run.

background is.... i download all the symbols from my broker then check some metrics on them using yfinance
Exception in thread Thread-320:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/urllib3/response.py", line 685, in _update_chunk_length
    self.chunk_left = int(line, 16)
ValueError: invalid literal for int() with base 16: b''

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/urllib3/response.py", line 425, in _error_catcher
    yield
  File "/usr/lib/python3/dist-packages/urllib3/response.py", line 752, in read_chunked
    self._update_chunk_length()
  File "/usr/lib/python3/dist-packages/urllib3/response.py", line 689, in _update_chunk_length
    raise httplib.IncompleteRead(line)
http.client.IncompleteRead: IncompleteRead(0 bytes read)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/requests/models.py", line 816, in generate
    yield from self.raw.stream(chunk_size, decode_content=True)
  File "/usr/lib/python3/dist-packages/urllib3/response.py", line 560, in stream
    for line in self.read_chunked(amt, decode_content=decode_content):
  File "/usr/lib/python3/dist-packages/urllib3/response.py", line 781, in read_chunked
    self._original_response.close()
  File "/usr/lib/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/lib/python3/dist-packages/urllib3/response.py", line 443, in _error_catcher
    raise ProtocolError("Connection broken: %r" % e, e)
urllib3.exceptions.ProtocolError: ('Connection broken: IncompleteRead(0 bytes read)', IncompleteRead(0 bytes read))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.8/dist-packages/multitasking/__init__.py", line 104, in _run_via_pool
    return callee(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/yfinance/multi.py", line 199, in _download_one_threaded
    data = _download_one(ticker, start, end, auto_adjust, back_adjust,
  File "/usr/local/lib/python3.8/dist-packages/yfinance/multi.py", line 213, in _download_one
    return Ticker(ticker).history(period=period, interval=interval,
  File "/usr/local/lib/python3.8/dist-packages/yfinance/base.py", line 153, in history
    tz = self._get_ticker_tz()
  File "/usr/local/lib/python3.8/dist-packages/yfinance/base.py", line 345, in _get_ticker_tz
    if not 'exchangeTimezoneName' in self.info:
  File "/usr/local/lib/python3.8/dist-packages/yfinance/ticker.py", line 147, in info
    return self.get_info()
  File "/usr/local/lib/python3.8/dist-packages/yfinance/base.py", line 711, in get_info
    self._get_info(proxy)
  File "/usr/local/lib/python3.8/dist-packages/yfinance/base.py", line 377, in _get_info
    data = utils.get_json(ticker_url, proxy, self.session)
  File "/usr/local/lib/python3.8/dist-packages/yfinance/utils.py", line 113, in get_json
    html = session.get(url=url, proxies=proxy, headers=user_agent_headers).text
  File "/usr/local/lib/python3.8/dist-packages/requests/api.py", line 73, in get
    return request("get", url, params=params, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/requests/api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/requests/sessions.py", line 587, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.8/dist-packages/requests/sessions.py", line 745, in send
    r.content
  File "/usr/local/lib/python3.8/dist-packages/requests/models.py", line 899, in content
    self._content = b"".join(self.iter_content(CONTENT_CHUNK_SIZE)) or b""
  File "/usr/local/lib/python3.8/dist-packages/requests/models.py", line 818, in generate
    raise ChunkedEncodingError(e)
requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRead(0 bytes read)', IncompleteRead(0 bytes read))
downloaded the branch again and now im getting a different error as above

BRK.B is now working fine though
[*********************100%***********************]  1 of 1 completed

1 Failed download:
- BRK.B: No data found for this date range, symbol may be delisted
error getting or processing data

Well of course you get an error, BRK.B is an illegal value. It's not on Yahoo as I've already said.
sorry to be clear BRK.B is now working as expected and returns "no data found for this date range, symbol might be delisted"

however a different symbol is still not being handled properly and is returning that longer error that i posted above.
I can't debug your errors remotely. I need to know ticker to reproduce here.
it was COO, but ive re run a second time and its processed it fine.

i do appreciate you looking at this and apologies if it turns out to be my stupidity.

on a positive note, whatever you did in the branch has fixed the handling of the errors i was seeing before. i will continue to run this code and let you know if i get any other errors like above.
this time recieved the same error as above on HCSG
I cannot reproduce your errors so you may have to debug yourself. They look like your network connection is bad, nothing to do with yfinance.
thanks for your help on the original error.
I've moved the fixes into git branch 'feature/improve-tz-cache'. Eventually I'll send it to PIP, maybe 1-2 weeks - I have some other fixes to do.
Hello,

I can't find the branch named  'feature/improve-tz-cache' on github.

I am suffering the same problem (AttributeError: 'float' object has no attribute 'upper') with the PIP version (0.1.84).

I have also downloaded the version from github as you mentioned previously. I get another error :

################## cut
(...)
self.conn.executemany('replace into "kv" (key, value) values (?,?)', records)
sqlite3.IntegrityError: NOT NULL constraint failed: kv.key
################## cut

It is located in "yfinance/yfinance/utils.py", line 558, in bulk_set"

Any idea or branch that I can use to get a working version?
Thanks.

Ignore that sqlite error. I've just release 0.1.85, that should fix problems.
I have installed the new 0.1.85.
Well it works for a good ticker like MMM. But if I try SDLP as a ticker then it does not work.

I have just tried with bpython3 with 2 lines of code : 
import yfinance as yf
mydf = yf.download('SDLP', start='2022-09-12', end='2022-11-02')

I never get back to the prompt ! I need to break with ctrl-C.
When I hit the Ctrl-C I get those lines :

########################### cut
Got error from yahoo api for ticker SDLP, Error: {'code': 'Not Found', 'description': 'No data found, symbol may be
 delisted'}Exception in thread Exception in threading.excepthook:Exception ignored in thread started byException ig
nored in sys.unraisablehookTraceback (most recent call last):
  File "<input>", line 1, in <module>
    mydf = yf.download('SDLP', start='2022-09-12', end='2022-11-02')
  File "/home/richard/.local/lib/python3.8/site-packages/yfinance/multi.py", line 118, in download
    _time.sleep(0.01)
  File "/usr/lib/python3/dist-packages/bpython/curtsiesfrontend/coderunner.py", line 176, in sigint_handler
    raise KeyboardInterrupt()
KeyboardInterrupt
########################### cut

But with 'MMM' for example (a good ticker) it works.

Maybe this feedback can help.

Ok, I think I've fixed that too. But this time I'll be careful and won't publish until you test - grab branch "release/0.1"
I have switched to "release/0.1".

I have tested with jupyter : it works.
I have tested with bpython3 : it does not work for delisted ticker. Here is an output : 

############################################################ cut
bpython version 0.18 on top of Python 3.8.10 /usr/bin/python3
>>> import sys
>>> sys.path.insert(0, "/home/richard/programmation/python/from_git/yfinance")
>>> import yfinance as yf
>>> print(yf)
<module 'yfinance' from '/home/richard/programmation/python/from_git/yfinance/yfinance/__init__.py'>
>>> 
>>> 
>>> code = 'SDLP'
>>> mydf = yf.download(code, start='2022-09-12', end='2022-11-02')
Got error from yahoo api for ticker SDLP, Error: {'code': 'Not Found', 'description': 'No data found, symbol may be
 delisted'}Exception in thread Exception in threading.excepthook:Exception ignored in thread started byException ig
nored in sys.unraisablehookTraceback (most recent call last):
  File "<input>", line 1, in <module>
    mydf = yf.download(code, start='2022-09-12', end='2022-11-02')
  File "/home/richard/programmation/python/from_git/yfinance/yfinance/multi.py", line 118, in download
    _time.sleep(0.01)
  File "/usr/lib/python3/dist-packages/bpython/curtsiesfrontend/coderunner.py", line 176, in sigint_handler
    raise KeyboardInterrupt()
KeyboardInterrupt
>>>
############################################################ cut

The program is stuck after calling "mydf = yf.download(...". I need to hit ctrl-C.


Try deleting this folder: $HOME/.cache/py-yfinance

If still error, convince me you have correct branch:

In shell: `git status`

In Python: `yf.__version__`
############################################### snip
richard@pluton1: ~/programmation/python/from_git/yfinance$ git checkout release/0.1
Branch 'release/0.1' set up to track remote branch 'release/0.1' from 'origin'.
Switched to a new branch 'release/0.1'
richard@pluton1: ~/programmation/python/from_git/yfinance$ 
richard@pluton1: ~/programmation/python/from_git/yfinance$ git branch
  main
* release/0.1
richard@pluton1: ~/programmation/python/from_git/yfinance$ git status
On branch release/0.1
Your branch is up to date with 'origin/release/0.1'.

nothing to commit, working tree clean
############################################### snip

next :

############################################### snip
richard@pluton1: ~/programmation/python/tests$ cat yahoo_new.py 
# coding: utf-8

import sys
sys.path.insert(0, "/home/richard/programmation/python/from_git/yfinance")

import yfinance as yf
print(yf)
print(yf.__version__)
print()

# code = 'MMM'
code = 'SDLP'

mydf = yf.download(code, start='2022-09-12', end='2022-11-02')
print(mydf)

richard@pluton1: ~/programmation/python/tests$ 
richard@pluton1: ~/programmation/python/tests$ ll
total 4
-rw-rw-r-- 1 richard richard 273 nov.   5 09:07 yahoo_new.py
richard@pluton1: ~/programmation/python/tests$ python3 yahoo_new.py 
<module 'yfinance' from '/home/richard/programmation/python/from_git/yfinance/yfinance/__init__.py'>
0.1.85

Got error from yahoo api for ticker SDLP, Error: {'code': 'Not Found', 'description': 'No data found, symbol may be delisted'}
[*********************100%***********************]  1 of 1 completed

1 Failed download:
- SDLP: No data found for this date range, symbol may be delisted
Empty DataFrame
Columns: [Open, High, Low, Close, Adj Close, Volume]
Index: []
############################################### snip

Next on bpython3 : 

############################################### snip
richard@pluton1: ~/programmation/python/tests$ bpython3
bpython version 0.18 on top of Python 3.8.10 /usr/bin/python3
>>> import sys
>>> sys.path.insert(0, "/home/richard/programmation/python/from_git/yfinance")
>>> import yfinance as yf
>>> print(yf)
<module 'yfinance' from '/home/richard/programmation/python/from_git/yfinance/yfinance/__init__.py'>
>>> print(yf.__version__)
0.1.85
>>> code = 'SDLP'
>>> mydf = yf.download(code, start='2022-09-12', end='2022-11-02')
Got error from yahoo api for ticker SDLP, Error: {'code': 'Not Found', 'description': 'No data found, symb
ol may be delisted'}Exception in thread Exception in threading.excepthook:Exception ignored in thread star
ted byException ignored in sys.unraisablehookTraceback (most recent call last):
  File "<input>", line 1, in <module>
    mydf = yf.download(code, start='2022-09-12', end='2022-11-02')
  File "/home/richard/programmation/python/from_git/yfinance/yfinance/multi.py", line 118, in download
    _time.sleep(0.01)
  File "/usr/lib/python3/dist-packages/bpython/curtsiesfrontend/coderunner.py", line 176, in sigint_handle
r
    raise KeyboardInterrupt()
KeyboardInterrupt
############################################### snip

On jupyter it is also 0.1.85 and it works.
It is bpython3 that waits indefinitely. I need to hit the ctrl-C.

But I haven't removed $HOME/.cache/py-yfinance yet. So I will do it now and I will let you know right after.








So I have removed $HOME/.cache/py-yfinance
Nothing changed : what worked still work and what didn't work still not work.

The interesting thing is that the directory $HOME/.cache/py-yfinance was not recreated by none of the steps I followed.

I will test with the Ticker class because for the moment I only use the 'download' function.


So the results : 

With the Ticker class and bpython3 I go back to the prompt ! Good !

Everything else work.

So the problem is in the download function. So perhaps the better way is to only use the Ticker class and not the download function.
Well I don't know the reason for maintaining two different ways to handle historic values. Maybe for historical reason with the original version of the Yahoo thing.

So I will go with the Ticker class.

Oh by the way, the directory $HOME/.cache/py-yfinance was never recreated. Normal or not?

Thanks for the help Ran and for your work.
Richard

Just a note : the output of the download function is not exactly the same as the output of Ticker.history.
Ah, bpython. Good news is I can reproduce your error so can investigate and hopefully fix.

`download()` is really intended for multiple tickers, downloads in parallel with threads then combines into single table.

I'm not Ran btw

Resolving patch:
diff --git a/yfinance/base.py b/yfinance/base.py
--- a/yfinance/base.py
+++ b/yfinance/base.py
@@ -145,6 +145,9 @@ def history(self, period="1mo", interval="1d",
         debug_mode = True
         if "debug" in kwargs and isinstance(kwargs["debug"], bool):
             debug_mode = kwargs["debug"]
+        if "many" in kwargs and kwargs["many"]:
+            # Disable prints with threads, it deadlocks/throws
+            debug_mode = False
 
         err_msg = "No data found for this date range, symbol may be delisted"
 
@@ -155,7 +158,7 @@ def history(self, period="1mo", interval="1d",
                 # Every valid ticker has a timezone. Missing = problem
                 shared._DFS[self.ticker] = utils.empty_df()
                 shared._ERRORS[self.ticker] = err_msg
-                if "many" not in kwargs and debug_mode:
+                if debug_mode:
                     print('- %s: %s' % (self.ticker, err_msg))
                 return utils.empty_df()
 
@@ -215,7 +218,7 @@ def history(self, period="1mo", interval="1d",
         if data is None or not type(data) is dict or 'status_code' in data.keys():
             shared._DFS[self.ticker] = utils.empty_df()
             shared._ERRORS[self.ticker] = err_msg
-            if "many" not in kwargs and debug_mode:
+            if debug_mode:
                 print('- %s: %s' % (self.ticker, err_msg))
             return utils.empty_df()
 
@@ -223,7 +226,7 @@ def history(self, period="1mo", interval="1d",
             err_msg = data["chart"]["error"]["description"]
             shared._DFS[self.ticker] = utils.empty_df()
             shared._ERRORS[self.ticker] = err_msg
-            if "many" not in kwargs and debug_mode:
+            if debug_mode:
                 print('- %s: %s' % (self.ticker, err_msg))
             return shared._DFS[self.ticker]
 
@@ -231,7 +234,7 @@ def history(self, period="1mo", interval="1d",
                 not data["chart"]["result"]:
             shared._DFS[self.ticker] = utils.empty_df()
             shared._ERRORS[self.ticker] = err_msg
-            if "many" not in kwargs and debug_mode:
+            if debug_mode:
                 print('- %s: %s' % (self.ticker, err_msg))
             return shared._DFS[self.ticker]
 
@@ -246,7 +249,7 @@ def history(self, period="1mo", interval="1d",
         except Exception:
             shared._DFS[self.ticker] = utils.empty_df()
             shared._ERRORS[self.ticker] = err_msg
-            if "many" not in kwargs and debug_mode:
+            if debug_mode:
                 print('- %s: %s' % (self.ticker, err_msg))
             return shared._DFS[self.ticker]
 
@@ -282,7 +285,7 @@ def history(self, period="1mo", interval="1d",
                 err_msg = "back_adjust failed with %s" % e
             shared._DFS[self.ticker] = utils.empty_df()
             shared._ERRORS[self.ticker] = err_msg
-            if "many" not in kwargs and debug_mode:
+            if debug_mode:
                 print('- %s: %s' % (self.ticker, err_msg))
 
         if rounding:
diff --git a/yfinance/multi.py b/yfinance/multi.py
--- a/yfinance/multi.py
+++ b/yfinance/multi.py
@@ -198,7 +198,7 @@ def _download_one_threaded(ticker, start=None, end=None,
 
     data = _download_one(ticker, start, end, auto_adjust, back_adjust,
                          actions, period, interval, prepost, proxy, rounding,
-                         keepna, timeout)
+                         keepna, timeout, many=True)
     shared._DFS[ticker.upper()] = data
     if progress:
         shared._PROGRESS_BAR.animate()
@@ -208,11 +208,11 @@ def _download_one(ticker, start=None, end=None,
                   auto_adjust=False, back_adjust=False,
                   actions=False, period="max", interval="1d",
                   prepost=False, proxy=None, rounding=False,
-                  keepna=False, timeout=None):
+                  keepna=False, timeout=None, many=False):
 
     return Ticker(ticker).history(period=period, interval=interval,
                                   start=start, end=end, prepost=prepost,
                                   actions=actions, auto_adjust=auto_adjust,
                                   back_adjust=back_adjust, proxy=proxy,
-                                  rounding=rounding, keepna=keepna, many=True,
-                                  timeout=timeout)
+                                  rounding=rounding, keepna=keepna, timeout=timeout, 
+                                  many=many)


Test patch: