Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows 10 - RuntimeError: Event loop is closed and UnicodeEncodeError: 'charmap' codec can't encode character #3

Closed
pybokeh opened this issue Aug 21, 2020 · 22 comments · Fixed by #6
Assignees
Labels
bug Something isn't working

Comments

@pybokeh
Copy link

pybokeh commented Aug 21, 2020

Not a bug, but perhaps it should be mentioned that databay will not work with Windows 10 due to a bug or the way asyncio chooses the default event loop mechanism, which throws an error, instead of just a warning.

So if running asyncio-dependent code on Windows machine, you will get an error similar below:

Traceback (most recent call last):
  File "C:\Programs\Python38\lib\asyncio\proactor_events.py", line 95, in __del__
    self.close()
  File "C:\Programs\Python38\lib\asyncio\proactor_events.py", line 86, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "C:\Programs\Python38\lib\asyncio\base_events.py", line 683, in call_soon
    self._check_closed()
  File "C:\Programs\Python38\lib\asyncio\base_events.py", line 475, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

Per this SO question, possible workaround is to use asyncio loop's run_until_complete() instead of just run()


(Update 1 by Voy - added more info)

To Reproduce
Example code (blockchain example):

import datetime

from databay.inlets import HttpInlet
from databay.outlets import PrintOutlet
from databay import Link
from databay.planners import APSPlanner

stock_inlet = HttpInlet('https://blockchain.info/ticker')

print_outlet = PrintOutlet(True, True)

link = Link(stock_inlet, print_outlet, interval=datetime.timedelta(seconds=1))

planner = APSPlanner(link)

planner.start()

Environment
Databay version: 0.1.2
Python version: 3.8.2
OS: Ubuntu 20.04 and Windows 10


(Update 2 by Voy - explaining the true issue)

The RuntimeError: Event loop is closed is only half of the problem here, and in fact is not the cause for the code to stop working, but a side effect happening when program terminates and can be fixed easily. The code wouldn't execute due to UnicodeEncodeError, which we figure out later down the line.

@pybokeh pybokeh added the documentation Improvements or additions to documentation label Aug 21, 2020
@Voyz Voyz added bug Something isn't working and removed documentation Improvements or additions to documentation labels Aug 21, 2020
@Voyz
Copy link
Owner

Voyz commented Aug 21, 2020

Thanks for reporting and doing some initial investigation into the issue!

To clarify: I've built the library on Windows 10, therefore Databay should hopefully be supported on that platform 😅 Let's try to figure out what is wrong here.

@Voyz Voyz self-assigned this Aug 21, 2020
@pybokeh
Copy link
Author

pybokeh commented Aug 21, 2020

@Voyz That's good to know that you want or plan for databay to work in Windows since I work in a corporate Windows environment. Even though my company does support containerization, unfortunately, our IT only supports containerized Java or .Net Core applications for now.

  • Does that issue appear when you're running some code in particular?
    Yes, the blockchain demo code that I referenced in the other issue.

  • Running it on Python 3.8.2 right?
    Yes

Too bad my OOP and async knowledge is very weak. Would love to help contribute to something like this. I did look at aiohttp's github issue for hints, but activity for this issue has been pretty stale. But, I think this is the official bug report from Python dot org. Here is an issue from httpx project, person submitted a possible workaround to use the selector event loop, instead of proactor event loop.

EDIT: Here is the workaround posted at httpx's repo:

import sys
import asyncio

if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

Not sure where to inject this code, I will see if can play around with this later and report back.

@Voyz
Copy link
Owner

Voyz commented Aug 21, 2020

@pybokeh Naturally, I certainly aim for Windows support and I'm very glad you reported this issue. I'm sure we can figure this one out 😊

Great job on investigating that issue - let me know if using the code you mentioned helps. The code you have could be placed in the initialise function in the config.py file, as it seems this should be applied to all instances of asyncio being used in Databay. Still, you can probably just drop it on the top of your Python script in which you're running the blockchain example to verify if it indeed helps.

Alternatively, the sources you linked seem to suggest replacing asyncio.run(...) with asyncio.get_event_loop().run_until_complete(...). If you'd be interested in participating, you'd be more than welcome to create a PR with that fix - change the line 227 in link.py. Otherwise I'll look into implementing the proposed changes soon.

Out of curiosity, could you check if swapping APSPlanner with SchedulePlanner fixes the issue?

@pybokeh
Copy link
Author

pybokeh commented Aug 21, 2020

Hey @Voyz
So far I've tried that workaround:

import sys
import asyncio

if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

by adding those snippets to my blockchain_demo.py:

import datetime
import sys
import asyncio
from databay.inlets import HttpInlet
from databay.outlets import PrintOutlet
from databay import Link
from databay.planners import APSPlanner

if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

stock_inlet = HttpInlet('https://blockchain.info/ticker')

print_outlet = PrintOutlet(True, True)

link = Link(stock_inlet, print_outlet,
            interval=datetime.timedelta(seconds=1))

planner = APSPlanner(link)
planner.start()

When executing, I no longer get an error, but nothing happens, the script may run maybe a second or two, then return control back to the terminal prompt.

Then I went to my local link.py and replaced:
asyncio.run(self._run()) with asyncio.get_event_loop().run_until_complete(self.run())

then ran my blockchain_demo.py (but commented out the lines from workaround above). I then get the following error message:

2020-08-21 17:33:12.445|E| There is no current event loop in thread 'ThreadPoolExecutor-0_0'.

Raised when executing Link.transfer (trigger: interval[0:00:01], next run at: 2020-08-21 17:33:13 EDT) (databay.APSPlanner)
Traceback (most recent call last):
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\planners\aps_planner.py", line 86, in _on_exception
    raise type(event.exception)(exception_message).with_traceback(traceback)
  File "D:\Python38\envs\streaming_dev\lib\site-packages\apscheduler\executors\base.py", line 125, in run_job
    retval = job.func(*job.args, **job.kwargs)
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 227, in transfer
    asyncio.get_event_loop().run_until_complete(self._run())
  File "D:\Python38\lib\asyncio\events.py", line 639, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'ThreadPoolExecutor-0_0'.

Raised when executing Link.transfer (trigger: interval[0:00:01], next run at: 2020-08-21 17:33:13 EDT)

I reverted my link.py to its original state. Then modified my local config.py to:

import sys
import asyncio

if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

def initialise():
    import logging

    from databay.misc.logs import ISO8601Formatter


    iso8601_formatter = ISO8601Formatter('%(asctime)s|%(levelname)-.1s| %(message)s (%(name)s)', millis_precision=3)# / %(threadName)s)')
    iso8601_formatter.set_pretty(True)

    stream_handler = logging.StreamHandler()
    stream_handler.setLevel(logging.DEBUG)
    stream_handler.setFormatter(iso8601_formatter)

    default_logger = logging.getLogger('databay')
    default_logger.addHandler(stream_handler)

    logging.getLogger('databay').setLevel(logging.WARNING)

Then executed my blockchain_demo.py and then get no error message, but no output also, it just returns control back to the terminal after about 1 or 2 seconds.

Finally, instead of using the APSPlanner, I used the SchedulerPlanner in my blockchain_demo.py. I get the same "RuntimeError: Event loop is closed()" traceback, but this time, the traceback is repeated continuously every second until I do CTRL+C several times.

Here's also an odd observation, when replacing asyncio.run(self._run()) with asyncio.get_event_loop().run_until_complete(self.run()), I did one time additionally get a syntax warning:

D:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py:37: SyntaxWarning: "is not" with a literal. Did you mean "!="?
  if self.name is not '': s += f'{self.name}.'

But what is odd is that the syntax warning happens infrequently or seldomly.

@Voyz
Copy link
Owner

Voyz commented Aug 22, 2020

Thank you for doing all these tests 🙌. I'm thoroughly confused by the behaviour you're experiencing - especially that I am unable to reproduce any of it. I've tried to run the examples with following permutations on my Microsoft Windows 10 Pro 10.0.19041 N/A Build 19041:

Python:

  • 3.7.7
  • 3.8.5
  • 3.8.2 (32 bit)
  • 3.8.2 (64 bit)
  • Using of virtual env
  • Not using virtual env

Using:

  • asyncio.run(self._run())
  • asyncio.get_event_loop().run_until_complete(self._run())
  • WindowsSelectorEventLoopPolicy
  • WindowsProactorEventLoopPolicy

Running both:

  • blockchain demo you listed above
  • examples/simple_usage.py

To no avail - the code executes fine in all instances and I can't nail down how to cause the event loop issue, or how to make the control flow to return to terminal upon setting the policy manually like you describe. Bugger.

I've read through the links you've left - very useful - thought couldn't find any more indication there. I'm guessing this may be issue related so some particular hardware or Windows version? Dunno, but worth giving it a shot:

  • Which version of Python are you on, 32 or 64 bit?

  • Could you provide me with more info about your OS? Run this in your terminal to get some deets:

    systeminfo | findstr /I /R /C:"OS Name" /C:"OS Version"

  • What CPU model are you on?

  • What's your pip freeze?

  • Any other spec you think could be influential to this issue. Are you on a virtual box maybe? Some particular setup of your Python env?

Really sorry about you running into these issues, I'm truly surprised I can't reproduce any of these. Appreciate your input trying to fix it, as this may be true for many other users too 👍

@pybokeh
Copy link
Author

pybokeh commented Aug 22, 2020

Hey @Voyz , below is my console output that shows my workflow, start-to-finish (I'm using cmder mini as my Windows terminal, so after the lambda symbol is the start of the terminal where I would enter the terminal commands). I am using my company's laptop and not on VPN, connected to home's network, using plain, vanilla Python, not Anaconda or miniconda3, version 3.8.4, 64-bit. I use Python's built-in venv module to create virtual environments.

I deleted my streaming_dev virtual environment folder that I've made previously and recreated it as in below to start from scatch:

D:\Python38\envs
λ python --version
Python 3.8.4

D:\Python38\envs
λ python -m venv streaming_dev

D:\Python38\envs
λ cd streaming_dev\

D:\Python38\envs\streaming_dev
λ Scripts\activate.bat

D:\Python38\envs\streaming_dev
(streaming_dev) λ pip install wheel --no-cache
Collecting wheel
  Downloading wheel-0.35.1-py2.py3-none-any.whl (33 kB)
Installing collected packages: wheel
Successfully installed wheel-0.35.1
WARNING: You are using pip version 20.1.1; however, version 20.2.2 is available.
You should consider upgrading via the 'd:\python38\envs\streaming_dev\scripts\python.exe -m pip install --upgrade pip' command.

D:\Python38\envs\streaming_dev
(streaming_dev) λ pip install databay[HttpInlet] --no-cache
Collecting databay[HttpInlet]
  Downloading databay-0.1.4.tar.gz (22 kB)
Collecting APScheduler<4.0.0
  Downloading APScheduler-3.6.3-py2.py3-none-any.whl (58 kB)
     |################################| 58 kB 990 kB/s
Collecting schedule<1.0.0
  Downloading schedule-0.6.0-py2.py3-none-any.whl (8.7 kB)
Collecting aiohttp>=3.6.2
  Downloading aiohttp-3.6.2-py3-none-any.whl (441 kB)
     |################################| 441 kB 2.2 MB/s
Collecting six>=1.4.0
  Downloading six-1.15.0-py2.py3-none-any.whl (10 kB)
Requirement already satisfied: setuptools>=0.7 in d:\python38\envs\streaming_dev\lib\site-packages (from APScheduler<4.0.0->databay[HttpInlet]) (47.1.0)
Collecting tzlocal>=1.2
  Downloading tzlocal-2.1-py2.py3-none-any.whl (16 kB)
Collecting pytz
  Downloading pytz-2020.1-py2.py3-none-any.whl (510 kB)
     |################################| 510 kB 6.8 MB/s
Collecting multidict<5.0,>=4.5
  Downloading multidict-4.7.6-cp38-cp38-win_amd64.whl (48 kB)
     |################################| 48 kB ...
Collecting async-timeout<4.0,>=3.0
  Downloading async_timeout-3.0.1-py3-none-any.whl (8.2 kB)
Collecting attrs>=17.3.0
  Downloading attrs-20.1.0-py2.py3-none-any.whl (49 kB)
     |################################| 49 kB 3.4 MB/s
Collecting yarl<2.0,>=1.0
  Downloading yarl-1.5.1-cp38-cp38-win_amd64.whl (128 kB)
     |################################| 128 kB 6.4 MB/s
Collecting chardet<4.0,>=2.0
  Downloading chardet-3.0.4-py2.py3-none-any.whl (133 kB)
     |################################| 133 kB 6.8 MB/s
Collecting idna>=2.0
  Downloading idna-2.10-py2.py3-none-any.whl (58 kB)
     |################################| 58 kB ...
Building wheels for collected packages: databay
  Building wheel for databay (setup.py) ... done
  Created wheel for databay: filename=databay-0.1.4-py3-none-any.whl size=29291 sha256=77eefc6ebabc1247bcc93aba3fa17e22ccf7d74e46d936bb5370c31aea59d770
  Stored in directory: C:\Users\some_user\AppData\Local\Temp\pip-ephem-wheel-cache-7bbf3_x8\wheels\11\e4\5a\2a412d0caf740279ac3c9cda538b4e276b884c12e9dd5c43a2
Successfully built databay
Installing collected packages: six, pytz, tzlocal, APScheduler, schedule, multidict, async-timeout, attrs, idna, yarl, chardet, aiohttp, databay
Successfully installed APScheduler-3.6.3 aiohttp-3.6.2 async-timeout-3.0.1 attrs-20.1.0 chardet-3.0.4 databay-0.1.4 idna-2.10 multidict-4.7.6 pytz-2020.1 schedule-0.6.0 six-1.15.0 tzlocal-2.1 yarl-1.5.1
WARNING: You are using pip version 20.1.1; however, version 20.2.2 is available.
You should consider upgrading via the 'd:\python38\envs\streaming_dev\scripts\python.exe -m pip install --upgrade pip' command.

D:\Python38\envs\streaming_dev
(streaming_dev) λ cat blockchain_demo.py
import datetime
#import sys
#import asyncio
from databay.inlets import HttpInlet
from databay.outlets import PrintOutlet
from databay import Link
from databay.planners import APSPlanner

#if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
#    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

stock_inlet = HttpInlet('https://blockchain.info/ticker')

print_outlet = PrintOutlet(True, True)

link = Link(stock_inlet, print_outlet,
            interval=datetime.timedelta(seconds=1))

planner = APSPlanner(link)
planner.start()
D:\Python38\envs\streaming_dev
(streaming_dev) λ python blockchain_demo.py
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000002598D64CF70>
Traceback (most recent call last):
  File "D:\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

### This is where I've uncommented the lines for the workaround and then executed ###

D:\Python38\envs\streaming_dev
(streaming_dev) λ cat blockchain_demo.py
import datetime
import sys
import asyncio
from databay.inlets import HttpInlet
from databay.outlets import PrintOutlet
from databay import Link
from databay.planners import APSPlanner

if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

stock_inlet = HttpInlet('https://blockchain.info/ticker')

print_outlet = PrintOutlet(True, True)

link = Link(stock_inlet, print_outlet,
            interval=datetime.timedelta(seconds=1))

planner = APSPlanner(link)
planner.start()
D:\Python38\envs\streaming_dev
(streaming_dev) λ python blockchain_demo.py
 
### No output at all, control returned back to terminal ###

D:\Python38\envs\streaming_dev
(streaming_dev) λ

D:\Python38\envs\streaming_dev
(streaming_dev) λ systeminfo | findstr /I /R /C:"OS Name" /C:"OS Version"
OS Name:                   Microsoft Windows 10 Enterprise
OS Version:                10.0.17763 N/A Build 17763
BIOS Version:              Dell Inc. 1.19.3, 8/20/2018

D:\Python38\envs\streaming_dev
(streaming_dev) λ pip freeze
aiohttp==3.6.2
APScheduler==3.6.3
async-timeout==3.0.1
attrs==20.1.0
chardet==3.0.4
databay==0.1.4
idna==2.10
multidict==4.7.6
pytz==2020.1
schedule==0.6.0
six==1.15.0
tzlocal==2.1
yarl==1.5.1

D:\Python38\envs\streaming_dev
(streaming_dev) λ

I am not using VM, just native OS and hardware.
OS: Microsoft Windows 10 Enterprise
Dell laptop, 16GB of RAM, i5-6300U CPU @ 2.40Ghz , 2 cores, 4 logical processors, Hyper-V options turned on.

Yes, that is strange that everything is fine with your setup. Curious, if others are experiencing the same issue as me. Can't think of anything else to share at the moment that might explain for the difference.

@pybokeh pybokeh changed the title asyncio-related error when using datadog with Windows 10 - RuntimeError: Event loop is closed asyncio-related error when using databay with Windows 10 - RuntimeError: Event loop is closed Aug 22, 2020
@pybokeh
Copy link
Author

pybokeh commented Aug 22, 2020

@Voyz
I installed miniconda3 so that I can create a Python 3.7 environment (version 3.7.8). When running the blockchain_demo.py, I do not get an error, but I do not get any output either, it just returns control back to terminal after about 2 seconds. I wonder if something is wrong with the PrintOutlet, but if exact same code is working for you, that is very strange. I also ran the code using the standard Windows terminal and same thing occurs, to rule out whether or not cmder mini handles terminal output differently than Windows' "command prompt" terminal.

@Voyz
Copy link
Owner

Voyz commented Aug 23, 2020

Thanks for doing all these tests. I work with CMDER too and also tested both that and native CMD - things are working well on both ends, but it's good you did that test. Also thanks for providing all the environment info - can't see anything out of the ordinary there for now.

I've run a few tests on 3.8.4 using the exact same code as you did, with a fresh venv and still not no avail. However, I'm starting to suspect that the Event loop ... error is actually not what we're struggling with, but a side effect of it. I see it sometimes when I CTRL+C out of the process when running your blockchain demo (or other examples). Also self.close() listed in the stack trace suggests that this exception is thrown during some sort of shutdown. If you had an IDE with a Python debugger that could catch exceptions, you should be able to see the full stack trace and understand at which point does the code break - I suspect it will be on script exit.

What's more, I can get some confirmation of this theory, by running the following snippet:

import asyncio
import json
import aiohttp

url = 'https://blockchain.info/ticker'

async def task():
    async with aiohttp.ClientSession() as session:
        async with session.get('https://blockchain.info/ticker') as response:
            payload = await response.read()
            print(json.loads(payload))

asyncio.run(task())

Each time when run on 3.8.4 venv, it prints once, then throws the Event loop is closed error. Adding the WindowsSelectorEventLoopPolicy code removes that problem.

Another easy way you could verify this, would be to put a print('end!') at the end of your script, after planner.start(). If this print executes before the Event loop... exception, we know the control flow was resumed on the main thread.

My observation therefore is:

  • The issue is not the Event loop is closed - it is a side effect. We should aim to fix it too, but it isn't the cause.
  • Instead, for some reason the script finishes prematurely when running the examples on your machine

If that hypothesis is true, we should aim to understand why does your script exit instead of running continuously. As of current version, both APSPlanner and SchedulePlanner treat start() as a blocking function, therefore execution should not be returned to the main thread after calling it. What we're seeing seems to suggest that opposite happens, and script resumes and exits.

In case of APSPlanner, blocking is handled externally by APS, and should happen within the _main_loop method of the BlockingScheduler - see source code. I've looked at the conditional logic of starting that APS scheduler, and it seems to be in order. Once again, if you had access to a Python debugger, and could step through the starting of APS to verify that the while loop (BlockingScheduler line 24) is indeed running and looping - that would bring some light onto the case (Put the breakpoint in _start_planner of APSPlanner). Furthermore, Databay suppresses some exceptions from APS logger, therefore you may want to call logging.getLogger('apscheduler.executors').setLevel(logging.DEBUG) after your script runs from databay.planners import APSPlanner in case we're missing something there.

Another method I could think of would be to try to understand how soon that while loop stops (if it indeed does). You could do that by replacing the last lines of blockchain demo with the following:

planner = APSPlanner(link)
# planner.start()

import threading
import time
th = threading.Thread(target=planner.start)
th.start()
while True:
    print(planner.running, th.is_alive())
    time.sleep(0.1)

What happens when you run this? What is being printed and does it change at some point? Does that while True loop continue executing, or does it stop too?

Finally, I'd suggest trying to run some examples from the examples folder. Majority of these don't use aiohttp, which should help us understand if possibly it is causing the issue here. Try starting with basic_inlet and intermediate_outlet.

@pybokeh
Copy link
Author

pybokeh commented Aug 23, 2020

@Voyz
I included your code snippet from above at the end of my blockchain_demo.py:

import datetime                                                                                                                                                               
import time                                                                                    
from databay.inlets import HttpInlet                                                           
from databay.outlets import PrintOutlet                                                        
from databay import Link                                                                       
from databay.planners import APSPlanner                                        
                                                                                               
stock_inlet = HttpInlet('https://blockchain.info/ticker')                                      
                                                                                               
print_outlet = PrintOutlet(True, True)                                                         
                                                                                               
link = Link(stock_inlet, print_outlet,                                                         
            interval=datetime.timedelta(seconds=1))                                            
                                                                                               
planner = APSPlanner(link)                                                                                                                            
#planner.start()                                                                               
                                                                                               
import threading                                                                               
th = threading.Thread(target=planner.start)                                                    
th.start()                                                                                     
                                                                                               
while True:                                                                                    
    print(planner.running, th.is_alive())                                                      
    time.sleep(0.1)                                                                            

This is the output in my console:

(streaming_dev) λ python blockchain_demo.py
True True
True True
True True
True True
True True
True True
True True
True True
True True
True True
True True
True True
True True
True True
True True
True True
True True
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
False False
Traceback (most recent call last):
  File "blockchain_demo.py", line 30, in <module>
    time.sleep(0.1)
KeyboardInterrupt
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000015EDB474310>
Traceback (most recent call last):
  File "D:\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
^C

This was executed on the plain, vanilla Python 3.8.4 environment.
So it prints out a series of "True True" then it prints "False False" and runs continuously until I ctrl-c.

I will do the rest of the stuff that you suggest later on today.

@Voyz
Copy link
Owner

Voyz commented Aug 23, 2020

Great, that's clear the APS starts and is running for a short while before shutting down after approx. 2 seconds like you reported previously. It doesn't fail to start completely. Additionally, I just wanted to confirm there's nothing strangely weird with while loops on your end, so we know that isn't the case either. Something must shut the APS down. It's strange that this behaviour would happen also with SchedulePlanner, given they use different scheduling logic. Could it be that threading is the cause? Or the fact we use asyncio? I'll prep a branch for you with no asyncio and so we can eliminate it from the list.

You can revert back to the previous version of your script - without that extra threading and while loop code - so that we don't miss any output otherwise hidden behind that thread.

This snipped also seems to confirm my theory - the Event loop... error is thrown way after the execution stops and is independent from Databay. Good to know that. That fix you found with WindowsSelectorEventLoopPolicy should sort that out, so good job on that one 👍

I'd add one more suggestion to the previous ones: add logging.getLogger('databay').setLevel(logging.DEBUG) before starting the planner - it should bring more verbosity to the execution too. Then you should at least see some messages about the start of scheduling.

Thanks in advance for running the additional tests I described above. I understand this must be annoying, so just wanna say I really appreciate you helping me find the culprit of this issue. And sorry for some delay with responses - I have a feeling our timezones are way out of sync, though I try to reply as soon as I see your comments.

@pybokeh
Copy link
Author

pybokeh commented Aug 23, 2020

@Voyz
OK, I've used a debugger and so hopefully this will shed some more light. I enabled logging into my blockchain_demo.py file so that it now looks like this:

import datetime
import logging
import time
from databay.inlets import HttpInlet
from databay.outlets import PrintOutlet
from databay import Link
from databay.planners import APSPlanner
logging.getLogger('apscheduler.executors').setLevel(logging.DEBUG)

stock_inlet = HttpInlet('https://blockchain.info/ticker')

print_outlet = PrintOutlet(True, True)

link = Link(stock_inlet, print_outlet,
            interval=datetime.timedelta(seconds=1))

planner = APSPlanner(link)
planner.start()

and I also added breakpoint() right before the line: self._scheduler_start() in the _start_planner() method found in your https://github.com/Voyz/databay/blob/master/databay/planners/aps_planner.py#L133

Then executed the script using pdb:

D:\Python38\envs\streaming_dev
(streaming_dev) λ python -m pdb blockchain_demo.py
> d:\python38\envs\streaming_dev\blockchain_demo.py(2)<module>()
-> import datetime
(Pdb) c
> d:\python38\envs\streaming_dev\lib\site-packages\databay\planners\aps_planner.py(134)_start_planner()
-> self._scheduler.start()
(Pdb) c
Job "Link.transfer (trigger: interval[0:00:01], next run at: 2020-08-23 11:21:42 EDT)" raised an exception
Traceback (most recent call last):
  File "D:\Python38\envs\streaming_dev\lib\site-packages\apscheduler\executors\base.py", line 125, in run_job
    retval = job.func(*job.args, **job.kwargs)
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 227, in transfer
    asyncio.run(self._run())
  File "D:\Python38\lib\asyncio\runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "D:\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
    return future.result()
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 306, in _run
    await asyncio.gather(*outlet_tasks)
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 296, in outlet_task
    raise e
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 291, in outlet_task
    await outlet._push(records_copy, update)
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\outlet.py", line 37, in _push
    rv = await self.push(records, update)
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\outlets\print_outlet.py", line 37, in push
    print(f'{update}{body}')
  File "D:\Python38\lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u20b9' in position 1120: character maps to <undefined>
The program finished and will be restarted
> d:\python38\envs\streaming_dev\blockchain_demo.py(2)<module>()
-> import datetime
(Pdb)

However, if I run VS Code's debugger, I get output in it's debug console terminal. I can see that the RuntimeError: Event loop is closed exception is thrown, but json data would still output:

Here's the output from VS Code's debug terminal:

Microsoft Windows [Version 10.0.17763.1397]
(c) 2018 Microsoft Corporation. All rights reserved.

D:\Python38\envs\streaming_dev> cmd /C "d:\Python38\envs\streaming_dev\Scripts\python.exe c:\Users\some_user\.vscode\extensions\ms-python.python-2020.8.103604\pythonFiles\lib\python\debugpy\launcher 50649 -- d:\Python38\envs\streaming_dev\blockchain_demo.py "
{'USD': {'15m': 11643.26, 'last': 11643.26, 'buy': 11643.26, 'sell': 11643.26, 'symbol': '$'}, 'AUD': {'15m': 16261.09, 'last': 16261.09, 'buy': 16261.09, 'sell': 16261.09, 'symbol': '$'}, 'BRL': {'15m': 65436.03, 'last': 65436.03, 'buy': 65436.03, 'sell': 65436.03, 'symbol': 'R$'}, 'CAD': {'15m': 15287.72, 'last': 15287.72, 'buy': 15287.72, 'sell': 15287.72, 'symbol': '$'}, 'CHF': {'15m': 10602.98, 'last': 10602.98, 'buy': 10602.98, 'sell': 10602.98, 'symbol': 'CHF'}, 'CLP': {'15m': 9234273.05, 'last': 9234273.05, 'buy': 9234273.05, 'sell': 9234273.05, 'symbol': '$'}, 'CNY': {'15m': 80565.56, 'last': 80565.56, 'buy': 80565.56, 'sell': 80565.56, 'symbol': '¥'}, 'DKK': {'15m': 73484.13, 'last': 73484.13, 'buy': 73484.13, 'sell': 73484.13, 'symbol': 'kr'}, 'EUR': {'15m': 9890.45, 'last': 9890.45, 'buy': 9890.45, 'sell': 9890.45, 'symbol': '€'}, 'GBP': {'15m': 8895.12, 'last': 8895.12, 'buy': 8895.12, 'sell': 8895.12, 'symbol': '£'}, 'HKD': {'15m': 90238.32, 'last': 90238.32, 'buy': 90238.32, 'sell': 90238.32, 'symbol': '$'}, 'INR': {'15m': 872421.59, 'last': 872421.59, 'buy': 872421.59, 'sell': 872421.59, 'symbol': '₹'}, 'ISK': {'15m': 1604791.02, 'last': 1604791.02, 'buy': 1604791.02, 'sell': 1604791.02, 'symbol': 'kr'}, 'JPY': {'15m': 1233125.77, 'last': 1233125.77, 'buy': 1233125.77, 'sell': 1233125.77, 'symbol': '¥'}, 'KRW': {'15m': 13881331.68,
'last': 13881331.68, 'buy': 13881331.68, 'sell': 13881331.68, 'symbol': '₩'}, 'NZD': {'15m': 17785.19, 'last': 17785.19, 'buy': 17785.19, 'sell': 17785.19, 'symbol': '$'}, 'PLN': {'15m': 43585.39, 'last': 43585.39, 'buy': 43585.39, 'sell': 43585.39, 'symbol': 'zł'}, 'RUB': {'15m': 871159.46, 'last': 871159.46, 'buy': 871159.46, 'sell': 871159.46, 'symbol': 'RUB'}, 'SEK': {'15m': 102570.75, 'last': 102570.75, 'buy': 102570.75, 'sell': 102570.75, 'symbol': 'kr'}, 'SGD': {'15m': 15969.78, 'last': 15969.78, 'buy': 15969.78, 'sell': 15969.78, 'symbol': '$'}, 'THB': {'15m': 367234.16, 'last': 367234.16, 'buy': 367234.16, 'sell': 367234.16, 'symbol': '฿'}, 'TRY': {'15m': 85380.05, 'last': 85380.05, 'buy': 85380.05, 'sell': 85380.05, 'symbol': '₺'}, 'TWD': {'15m': 342335.24, 'last': 342335.24, 'buy': 342335.24, 'sell': 342335.24, 'symbol': 'NT$'}}
{'USD': {'15m': 11642.04, 'last': 11642.04, 'buy': 11642.04, 'sell': 11642.04, 'symbol': '$'}, 'AUD': {'15m': 16259.38, 'last': 16259.38, 'buy': 16259.38, 'sell': 16259.38, 'symbol': '$'}, 'BRL': {'15m': 65429.17, 'last': 65429.17, 'buy': 65429.17, 'sell': 65429.17, 'symbol': 'R$'}, 'CAD': {'15m': 15286.12, 'last': 15286.12, 'buy': 15286.12, 'sell': 15286.12, 'symbol': '$'}, 'CHF': {'15m': 10601.87, 'last': 10601.87, 'buy': 10601.87, 'sell': 10601.87, 'symbol': 'CHF'}, 'CLP': {'15m': 9233305.46, 'last': 9233305.46, 'buy': 9233305.46, 'sell': 9233305.46, 'symbol': '$'}, 'CNY': {'15m': 80557.12, 'last': 80557.12, 'buy': 80557.12, 'sell': 80557.12, 'symbol': '¥'}, 'DKK': {'15m': 73476.43, 'last': 73476.43, 'buy': 73476.43, 'sell': 73476.43, 'symbol': 'kr'}, 'EUR': {'15m': 9889.45, 'last': 9889.45, 'buy': 9889.45, 'sell': 9889.45, 'symbol': '€'}, 'GBP': {'15m': 8894.18, 'last': 8894.18, 'buy': 8894.18, 'sell': 8894.18, 'symbol': '£'}, 'HKD': {'15m': 90228.86, 'last': 90228.86, 'buy': 90228.86, 'sell': 90228.86, 'symbol': '$'}, 'INR': {'15m': 872330.17, 'last': 872330.17, 'buy': 872330.17, 'sell': 872330.17, 'symbol': '₹'}, 'ISK': {'15m': 1604622.86, 'last': 1604622.86, 'buy': 1604622.86, 'sell': 1604622.86, 'symbol': 'kr'}, 'JPY': {'15m': 1232956.69, 'last': 1232956.69, 'buy': 1232956.69, 'sell': 1232956.69, 'symbol': '¥'}, 'KRW': {'15m': 13879877.15,
'last': 13879877.15, 'buy': 13879877.15, 'sell': 13879877.15, 'symbol': '₩'}, 'NZD': {'15m': 17783.33, 'last': 17783.33, 'buy': 17783.33, 'sell': 17783.33, 'symbol': '$'}, 'PLN': {'15m': 43580.83, 'last': 43580.83, 'buy': 43580.83, 'sell': 43580.83, 'symbol': 'zł'}, 'RUB': {'15m': 871068.18, 'last': 871068.18, 'buy': 871068.18, 'sell': 871068.18, 'symbol': 'RUB'}, 'SEK': {'15m': 102560.0, 'last': 102560.0, 'buy': 102560.0, 'sell': 102560.0, 'symbol': 'kr'}, 'SGD': {'15m': 15968.11, 'last': 15968.11, 'buy': 15968.11, 'sell': 15968.11, 'symbol': '$'}, 'THB': {'15m': 367195.68, 'last': 367195.68, 'buy': 367195.68, 'sell': 367195.68, 'symbol': '฿'}, 'TRY': {'15m': 85371.11, 'last': 85371.11, 'buy': 85371.11, 'sell': 85371.11, 'symbol': '₺'}, 'TWD': {'15m': 342299.36, 'last': 342299.36, 'buy': 342299.36, 'sell': 342299.36, 'symbol': 'NT$'}}
{'USD': {'15m': 11642.04, 'last': 11642.04, 'buy': 11642.04, 'sell': 11642.04, 'symbol': '$'}, 'AUD': {'15m': 16259.38, 'last': 16259.38, 'buy': 16259.38, 'sell': 16259.38, 'symbol': '$'}, 'BRL': {'15m': 65429.17, 'last': 65429.17, 'buy': 65429.17, 'sell': 65429.17, 'symbol': 'R$'}, 'CAD': {'15m': 15286.12, 'last': 15286.12, 'buy': 15286.12, 'sell': 15286.12, 'symbol': '$'}, 'CHF': {'15m': 10601.87, 'last': 10601.87, 'buy': 10601.87, 'sell': 10601.87, 'symbol': 'CHF'}, 'CLP': {'15m': 9233305.46, 'last': 9233305.46, 'buy': 9233305.46, 'sell': 9233305.46, 'symbol': '$'}, 'CNY': {'15m': 80557.12, 'last': 80557.12, 'buy': 80557.12, 'sell': 80557.12, 'symbol': '¥'}, 'DKK': {'15m': 73476.43, 'last': 73476.43, 'buy': 73476.43, 'sell': 73476.43, 'symbol': 'kr'}, 'EUR': {'15m': 9889.45, 'last': 9889.45, 'buy': 9889.45, 'sell': 9889.45, 'symbol': '€'}, 'GBP': {'15m': 8894.18, 'last': 8894.18, 'buy': 8894.18, 'sell': 8894.18, 'symbol': '£'}, 'HKD': {'15m': 90228.86, 'last': 90228.86, 'buy': 90228.86, 'sell': 90228.86, 'symbol': '$'}, 'INR': {'15m': 872330.17, 'last': 872330.17, 'buy': 872330.17, 'sell': 872330.17, 'symbol': '₹'}, 'ISK': {'15m': 1604622.86, 'last': 1604622.86, 'buy': 1604622.86, 'sell': 1604622.86, 'symbol': 'kr'}, 'JPY': {'15m': 1232956.69, 'last': 1232956.69, 'buy': 1232956.69, 'sell': 1232956.69, 'symbol': '¥'}, 'KRW': {'15m': 13879877.15,
'last': 13879877.15, 'buy': 13879877.15, 'sell': 13879877.15, 'symbol': '₩'}, 'NZD': {'15m': 17783.33, 'last': 17783.33, 'buy': 17783.33, 'sell': 17783.33, 'symbol': '$'}, 'PLN': {'15m': 43580.83, 'last': 43580.83, 'buy': 43580.83, 'sell': 43580.83, 'symbol': 'zł'}, 'RUB': {'15m': 871068.18, 'last': 871068.18, 'buy': 871068.18, 'sell': 871068.18, 'symbol': 'RUB'}, 'SEK': {'15m': 102560.0, 'last': 102560.0, 'buy': 102560.0, 'sell': 102560.0, 'symbol': 'kr'}, 'SGD': {'15m': 15968.11, 'last': 15968.11, 'buy': 15968.11, 'sell': 15968.11, 'symbol': '$'}, 'THB': {'15m': 367195.68, 'last': 367195.68, 'buy': 367195.68, 'sell': 367195.68, 'symbol': '฿'}, 'TRY': {'15m': 85371.11, 'last': 85371.11, 'buy': 85371.11, 'sell': 85371.11, 'symbol': '₺'}, 'TWD': {'15m': 342299.36, 'last': 342299.36, 'buy': 342299.36, 'sell': 342299.36, 'symbol': 'NT$'}}
{'USD': {'15m': 11642.04, 'last': 11642.04, 'buy': 11642.04, 'sell': 11642.04, 'symbol': '$'}, 'AUD': {'15m': 16259.38, 'last': 16259.38, 'buy': 16259.38, 'sell': 16259.38, 'symbol': '$'}, 'BRL': {'15m': 65429.17, 'last': 65429.17, 'buy': 65429.17, 'sell': 65429.17, 'symbol': 'R$'}, 'CAD': {'15m': 15286.12, 'last': 15286.12, 'buy': 15286.12, 'sell': 15286.12, 'symbol': '$'}, 'CHF': {'15m': 10601.87, 'last': 10601.87, 'buy': 10601.87, 'sell': 10601.87, 'symbol': 'CHF'}, 'CLP': {'15m': 9233305.46, 'last': 9233305.46, 'buy': 9233305.46, 'sell': 9233305.46, 'symbol': '$'}, 'CNY': {'15m': 80557.12, 'last': 80557.12, 'buy': 80557.12, 'sell': 80557.12, 'symbol': '¥'}, 'DKK': {'15m': 73476.43, 'last': 73476.43, 'buy': 73476.43, 'sell': 73476.43, 'symbol': 'kr'}, 'EUR': {'15m': 9889.45, 'last': 9889.45, 'buy': 9889.45, 'sell': 9889.45, 'symbol': '€'}, 'GBP': {'15m': 8894.18, 'last': 8894.18, 'buy': 8894.18, 'sell': 8894.18, 'symbol': '£'}, 'HKD': {'15m': 90228.86, 'last': 90228.86, 'buy': 90228.86, 'sell': 90228.86, 'symbol': '$'}, 'INR': {'15m': 872330.17, 'last': 872330.17, 'buy': 872330.17, 'sell': 872330.17, 'symbol': '₹'}, 'ISK': {'15m': 1604622.86, 'last': 1604622.86, 'buy': 1604622.86, 'sell': 1604622.86, 'symbol': 'kr'}, 'JPY': {'15m': 1232956.69, 'last': 1232956.69, 'buy': 1232956.69, 'sell': 1232956.69, 'symbol': '¥'}, 'KRW': {'15m': 13879877.15,
'last': 13879877.15, 'buy': 13879877.15, 'sell': 13879877.15, 'symbol': '₩'}, 'NZD': {'15m': 17783.33, 'last': 17783.33, 'buy': 17783.33, 'sell': 17783.33, 'symbol': '$'}, 'PLN': {'15m': 43580.83, 'last': 43580.83, 'buy': 43580.83, 'sell': 43580.83, 'symbol': 'zł'}, 'RUB': {'15m': 871068.18, 'last': 871068.18, 'buy': 871068.18, 'sell': 871068.18, 'symbol': 'RUB'}, 'SEK': {'15m': 102560.0, 'last': 102560.0, 'buy': 102560.0, 'sell': 102560.0, 'symbol': 'kr'}, 'SGD': {'15m': 15968.11, 'last': 15968.11, 'buy': 15968.11, 'sell': 15968.11, 'symbol': '$'}, 'THB': {'15m': 367195.68, 'last': 367195.68, 'buy': 367195.68, 'sell': 367195.68, 'symbol': '฿'}, 'TRY': {'15m': 85371.11, 'last': 85371.11, 'buy': 85371.11, 'sell': 85371.11, 'symbol': '₺'}, 'TWD': {'15m': 342299.36, 'last': 342299.36, 'buy': 342299.36, 'sell': 342299.36, 'symbol': 'NT$'}}
{'USD': {'15m': 11642.04, 'last': 11642.04, 'buy': 11642.04, 'sell': 11642.04, 'symbol': '$'}, 'AUD': {'15m': 16259.38, 'last': 16259.38, 'buy': 16259.38, 'sell': 16259.38, 'symbol': '$'}, 'BRL': {'15m': 65429.17, 'last': 65429.17, 'buy': 65429.17, 'sell': 65429.17, 'symbol': 'R$'}, 'CAD': {'15m': 15286.12, 'last': 15286.12, 'buy': 15286.12, 'sell': 15286.12, 'symbol': '$'}, 'CHF': {'15m': 10601.87, 'last': 10601.87, 'buy': 10601.87, 'sell': 10601.87, 'symbol': 'CHF'}, 'CLP': {'15m': 9233305.46, 'last': 9233305.46, 'buy': 9233305.46, 'sell': 9233305.46, 'symbol': '$'}, 'CNY': {'15m': 80557.12, 'last': 80557.12, 'buy': 80557.12, 'sell': 80557.12, 'symbol': '¥'}, 'DKK': {'15m': 73476.43, 'last': 73476.43, 'buy': 73476.43, 'sell': 73476.43, 'symbol': 'kr'}, 'EUR': {'15m': 9889.45, 'last': 9889.45, 'buy': 9889.45, 'sell': 9889.45, 'symbol': '€'}, 'GBP': {'15m': 8894.18, 'last': 8894.18, 'buy': 8894.18, 'sell': 8894.18, 'symbol': '£'}, 'HKD': {'15m': 90228.86, 'last': 90228.86, 'buy': 90228.86, 'sell': 90228.86, 'symbol': '$'}, 'INR': {'15m': 872330.17, 'last': 872330.17, 'buy': 872330.17, 'sell': 872330.17, 'symbol': '₹'}, 'ISK': {'15m': 1604622.86, 'last': 1604622.86, 'buy': 1604622.86, 'sell': 1604622.86, 'symbol': 'kr'}, 'JPY': {'15m': 1232956.69, 'last': 1232956.69, 'buy': 1232956.69, 'sell': 1232956.69, 'symbol': '¥'}, 'KRW': {'15m': 13879877.15,
'last': 13879877.15, 'buy': 13879877.15, 'sell': 13879877.15, 'symbol': '₩'}, 'NZD': {'15m': 17783.33, 'last': 17783.33, 'buy': 17783.33, 'sell': 17783.33, 'symbol': '$'}, 'PLN': {'15m': 43580.83, 'last': 43580.83, 'buy': 43580.83, 'sell': 43580.83, 'symbol': 'zł'}, 'RUB': {'15m': 871068.18, 'last': 871068.18, 'buy': 871068.18, 'sell': 871068.18, 'symbol': 'RUB'}, 'SEK': {'15m': 102560.0, 'last': 102560.0, 'buy': 102560.0, 'sell': 102560.0, 'symbol': 'kr'}, 'SGD': {'15m': 15968.11, 'last': 15968.11, 'buy': 15968.11, 'sell': 15968.11, 'symbol': '$'}, 'THB': {'15m': 367195.68, 'last': 367195.68, 'buy': 367195.68, 'sell': 367195.68, 'symbol': '฿'}, 'TRY': {'15m': 85371.11, 'last': 85371.11, 'buy': 85371.11, 'sell': 85371.11, 'symbol': '₺'}, 'TWD': {'15m': 342299.36, 'last': 342299.36, 'buy': 342299.36, 'sell': 342299.36, 'symbol': 'NT$'}}
{'USD': {'15m': 11642.04, 'last': 11642.04, 'buy': 11642.04, 'sell': 11642.04, 'symbol': '$'}, 'AUD': {'15m': 16259.38, 'last': 16259.38, 'buy': 16259.38, 'sell': 16259.38, 'symbol': '$'}, 'BRL': {'15m': 65429.17, 'last': 65429.17, 'buy': 65429.17, 'sell': 65429.17, 'symbol': 'R$'}, 'CAD': {'15m': 15286.12, 'last': 15286.12, 'buy': 15286.12, 'sell': 15286.12, 'symbol': '$'}, 'CHF': {'15m': 10601.87, 'last': 10601.87, 'buy': 10601.87, 'sell': 10601.87, 'symbol': 'CHF'}, 'CLP': {'15m': 9233305.46, 'last': 9233305.46, 'buy': 9233305.46, 'sell': 9233305.46, 'symbol': '$'}, 'CNY': {'15m': 80557.12, 'last': 80557.12, 'buy': 80557.12, 'sell': 80557.12, 'symbol': '¥'}, 'DKK': {'15m': 73476.43, 'last': 73476.43, 'buy': 73476.43, 'sell': 73476.43, 'symbol': 'kr'}, 'EUR': {'15m': 9889.45, 'last': 9889.45, 'buy': 9889.45, 'sell': 9889.45, 'symbol': '€'}, 'GBP': {'15m': 8894.18, 'last': 8894.18, 'buy': 8894.18, 'sell': 8894.18, 'symbol': '£'}, 'HKD': {'15m': 90228.86, 'last': 90228.86, 'buy': 90228.86, 'sell': 90228.86, 'symbol': '$'}, 'INR': {'15m': 872330.17, 'last': 872330.17, 'buy': 872330.17, 'sell': 872330.17, 'symbol': '₹'}, 'ISK': {'15m': 1604622.86, 'last': 1604622.86, 'buy': 1604622.86, 'sell': 1604622.86, 'symbol': 'kr'}, 'JPY': {'15m': 1232956.69, 'last': 1232956.69, 'buy': 1232956.69, 'sell': 1232956.69, 'symbol': '¥'}, 'KRW': {'15m': 13879877.15,
'last': 13879877.15, 'buy': 13879877.15, 'sell': 13879877.15, 'symbol': '₩'}, 'NZD': {'15m': 17783.33, 'last': 17783.33, 'buy': 17783.33, 'sell': 17783.33, 'symbol': '$'}, 'PLN': {'15m': 43580.83, 'last': 43580.83, 'buy': 43580.83, 'sell': 43580.83, 'symbol': 'zł'}, 'RUB': {'15m': 871068.18, 'last': 871068.18, 'buy': 871068.18, 'sell': 871068.18, 'symbol': 'RUB'}, 'SEK': {'15m': 102560.0, 'last': 102560.0, 'buy': 102560.0, 'sell': 102560.0, 'symbol': 'kr'}, 'SGD': {'15m': 15968.11, 'last': 15968.11, 'buy': 15968.11, 'sell': 15968.11, 'symbol': '$'}, 'THB': {'15m': 367195.68, 'last': 367195.68, 'buy': 367195.68, 'sell': 367195.68, 'symbol': '฿'}, 'TRY': {'15m': 85371.11, 'last': 85371.11, 'buy': 85371.11, 'sell': 85371.11, 'symbol': '₺'}, 'TWD': {'15m': 342299.36, 'last': 342299.36, 'buy': 342299.36, 'sell': 342299.36, 'symbol': 'NT$'}}
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000014D87A14310>
Traceback (most recent call last):
  File "D:\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000014D87A14310>
Traceback (most recent call last):
  File "D:\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000014D87A14310>
Traceback (most recent call last):
  File "D:\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000014D87A14310>
Traceback (most recent call last):
  File "D:\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
{'USD': {'15m': 11642.11, 'last': 11642.11, 'buy': 11642.11, 'sell': 11642.11, 'symbol': '$'}, 'AUD': {'15m': 16259.48, 'last': 16259.48, 'buy': 16259.48, 'sell': 16259.48, 'symbol': '$'}, 'BRL': {'15m': 65429.54, 'last': 65429.54, 'buy': 65429.54, 'sell': 65429.54, 'symbol': 'R$'}, 'CAD': {'15m': 15286.21, 'last': 15286.21, 'buy': 15286.21, 'sell': 15286.21, 'symbol': '$'}, 'CHF': {'15m': 10601.93, 'last': 10601.93, 'buy': 10601.93, 'sell': 10601.93, 'symbol': 'CHF'}, 'CLP': {'15m': 9233357.84, 'last': 9233357.84, 'buy': 9233357.84, 'sell': 9233357.84, 'symbol': '$'}, 'CNY': {'15m': 80557.58, 'last': 80557.58, 'buy': 80557.58, 'sell': 80557.58, 'symbol': '¥'}, 'DKK': {'15m': 73476.85, 'last': 73476.85, 'buy': 73476.85, 'sell': 73476.85, 'symbol': 'kr'}, 'EUR': {'15m': 9890.06, 'last': 9890.06, 'buy': 9890.06, 'sell': 9890.06, 'symbol': '€'}, 'GBP': {'15m': 8894.23, 'last': 8894.23, 'buy': 8894.23, 'sell': 8894.23, 'symbol': '£'}, 'HKD': {'15m': 90229.38, 'last': 90229.38, 'buy': 90229.38, 'sell': 90229.38, 'symbol': '$'}, 'INR': {'15m': 872335.12, 'last': 872335.12, 'buy': 872335.12, 'sell': 872335.12, 'symbol': '₹'}, 'ISK': {'15m': 1604631.97, 'last': 1604631.97, 'buy': 1604631.97, 'sell': 1604631.97, 'symbol': 'kr'}, 'JPY': {'15m': 1232965.4, 'last': 1232965.4, 'buy': 1232965.4, 'sell': 1232965.4, 'symbol': '¥'}, 'KRW': {'15m': 13879955.91, 'last': 13879955.91, 'buy': 13879955.91, 'sell': 13879955.91, 'symbol': '₩'}, 'NZD': {'15m': 17783.43, 'last': 17783.43, 'buy': 17783.43, 'sell': 17783.43, 'symbol': '$'}, 'PLN': {'15m': 43581.07, 'last': 43581.07, 'buy': 43581.07, 'sell': 43581.07, 'symbol': 'zł'}, 'RUB': {'15m': 871073.12, 'last': 871073.12, 'buy': 871073.12, 'sell': 871073.12, 'symbol': 'RUB'}, 'SEK': {'15m': 102560.58, 'last': 102560.58, 'buy': 102560.58, 'sell': 102560.58, 'symbol': 'kr'}, 'SGD': {'15m': 15968.2, 'last': 15968.2, 'buy': 15968.2, 'sell': 15968.2, 'symbol': '$'}, 'THB': {'15m': 367197.76, 'last': 367197.76, 'buy': 367197.76, 'sell': 367197.76, 'symbol': '฿'}, 'TRY': {'15m': 85371.59, 'last': 85371.59, 'buy': 85371.59, 'sell': 85371.59, 'symbol': '₺'}, 'TWD': {'15m': 342301.31, 'last': 342301.31, 'buy': 342301.31, 'sell': 342301.31, 'symbol': 'NT$'}}
{'USD': {'15m': 11642.04, 'last': 11642.04, 'buy': 11642.04, 'sell': 11642.04, 'symbol': '$'}, 'AUD': {'15m': 16259.38, 'last': 16259.38, 'buy': 16259.38, 'sell': 16259.38, 'symbol': '$'}, 'BRL': {'15m': 65429.17, 'last': 65429.17, 'buy': 65429.17, 'sell': 65429.17, 'symbol': 'R$'}, 'CAD': {'15m': 15286.12, 'last': 15286.12, 'buy': 15286.12, 'sell': 15286.12, 'symbol': '$'}, 'CHF': {'15m': 10601.87, 'last': 10601.87, 'buy': 10601.87, 'sell': 10601.87, 'symbol': 'CHF'}, 'CLP': {'15m': 9233305.46, 'last': 9233305.46, 'buy': 9233305.46, 'sell': 9233305.46, 'symbol': '$'}, 'CNY': {'15m': 80557.12, 'last': 80557.12, 'buy': 80557.12, 'sell': 80557.12, 'symbol': '¥'}, 'DKK': {'15m': 73476.43, 'last': 73476.43, 'buy': 73476.43, 'sell': 73476.43, 'symbol': 'kr'}, 'EUR': {'15m': 9889.45, 'last': 9889.45, 'buy': 9889.45, 'sell': 9889.45, 'symbol': '€'}, 'GBP': {'15m': 8894.18, 'last': 8894.18, 'buy': 8894.18, 'sell': 8894.18, 'symbol': '£'}, 'HKD': {'15m': 90228.86, 'last': 90228.86, 'buy': 90228.86, 'sell': 90228.86, 'symbol': '$'}, 'INR': {'15m': 872330.17, 'last': 872330.17, 'buy': 872330.17, 'sell': 872330.17, 'symbol': '₹'}, 'ISK': {'15m': 1604622.86, 'last': 1604622.86, 'buy': 1604622.86, 'sell': 1604622.86, 'symbol': 'kr'}, 'JPY': {'15m': 1232956.69, 'last': 1232956.69, 'buy': 1232956.69, 'sell': 1232956.69, 'symbol': '¥'}, 'KRW': {'15m': 13879877.15,
'last': 13879877.15, 'buy': 13879877.15, 'sell': 13879877.15, 'symbol': '₩'}, 'NZD': {'15m': 17783.33, 'last': 17783.33, 'buy': 17783.33, 'sell': 17783.33, 'symbol': '$'}, 'PLN': {'15m': 43580.83, 'last': 43580.83, 'buy': 43580.83, 'sell': 43580.83, 'symbol': 'zł'}, 'RUB': {'15m': 871068.18, 'last': 871068.18, 'buy': 871068.18, 'sell': 871068.18, 'symbol': 'RUB'}, 'SEK': {'15m': 102560.0, 'last': 102560.0, 'buy': 102560.0, 'sell': 102560.0, 'symbol': 'kr'}, 'SGD': {'15m': 15968.11, 'last': 15968.11, 'buy': 15968.11, 'sell': 15968.11, 'symbol': '$'}, 'THB': {'15m': 367195.68, 'last': 367195.68, 'buy': 367195.68, 'sell': 367195.68, 'symbol': '฿'}, 'TRY': {'15m': 85371.11, 'last': 85371.11, 'buy': 85371.11, 'sell': 85371.11, 'symbol': '₺'}, 'TWD': {'15m': 342299.36, 'last': 342299.36, 'buy': 342299.36, 'sell': 342299.36, 'symbol': 'NT$'}}
{'USD': {'15m': 11642.04, 'last': 11642.04, 'buy': 11642.04, 'sell': 11642.04, 'symbol': '$'}, 'AUD': {'15m': 16259.38, 'last': 16259.38, 'buy': 16259.38, 'sell': 16259.38, 'symbol': '$'}, 'BRL': {'15m': 65429.17, 'last': 65429.17, 'buy': 65429.17, 'sell': 65429.17, 'symbol': 'R$'}, 'CAD': {'15m': 15286.12, 'last': 15286.12, 'buy': 15286.12, 'sell': 15286.12, 'symbol': '$'}, 'CHF': {'15m': 10601.87, 'last': 10601.87, 'buy': 10601.87, 'sell': 10601.87, 'symbol': 'CHF'}, 'CLP': {'15m': 9233305.46, 'last': 9233305.46, 'buy': 9233305.46, 'sell': 9233305.46, 'symbol': '$'}, 'CNY': {'15m': 80557.12, 'last': 80557.12, 'buy': 80557.12, 'sell': 80557.12, 'symbol': '¥'}, 'DKK': {'15m': 73476.43, 'last': 73476.43, 'buy': 73476.43, 'sell': 73476.43, 'symbol': 'kr'}, 'EUR': {'15m': 9889.45, 'last': 9889.45, 'buy': 9889.45, 'sell': 9889.45, 'symbol': '€'}, 'GBP': {'15m': 8894.18, 'last': 8894.18, 'buy': 8894.18, 'sell': 8894.18, 'symbol': '£'}, 'HKD': {'15m': 90228.86, 'last': 90228.86, 'buy': 90228.86, 'sell': 90228.86, 'symbol': '$'}, 'INR': {'15m': 872330.17, 'last': 872330.17, 'buy': 872330.17, 'sell': 872330.17, 'symbol': '₹'}, 'ISK': {'15m': 1604622.86, 'last': 1604622.86, 'buy': 1604622.86, 'sell': 1604622.86, 'symbol': 'kr'}, 'JPY': {'15m': 1232956.69, 'last': 1232956.69, 'buy': 1232956.69, 'sell': 1232956.69, 'symbol': '¥'}, 'KRW': {'15m': 13879877.15,
'last': 13879877.15, 'buy': 13879877.15, 'sell': 13879877.15, 'symbol': '₩'}, 'NZD': {'15m': 17783.33, 'last': 17783.33, 'buy': 17783.33, 'sell': 17783.33, 'symbol': '$'}, 'PLN': {'15m': 43580.83, 'last': 43580.83, 'buy': 43580.83, 'sell': 43580.83, 'symbol': 'zł'}, 'RUB': {'15m': 871068.18, 'last': 871068.18, 'buy': 871068.18, 'sell': 871068.18, 'symbol': 'RUB'}, 'SEK': {'15m': 102560.0, 'last': 102560.0, 'buy': 102560.0, 'sell': 102560.0, 'symbol': 'kr'}, 'SGD': {'15m': 15968.11, 'last': 15968.11, 'buy': 15968.11, 'sell': 15968.11, 'symbol': '$'}, 'THB': {'15m': 367195.68, 'last': 367195.68, 'buy': 367195.68, 'sell': 367195.68, 'symbol': '฿'}, 'TRY': {'15m': 85371.11, 'last': 85371.11, 'buy': 85371.11, 'sell': 85371.11, 'symbol': '₺'}, 'TWD': {'15m': 342299.36, 'last': 342299.36, 'buy': 342299.36, 'sell': 342299.36, 'symbol': 'NT$'}}
{'USD': {'15m': 11642.04, 'last': 11642.04, 'buy': 11642.04, 'sell': 11642.04, 'symbol': '$'}, 'AUD': {'15m': 16259.38, 'last': 16259.38, 'buy': 16259.38, 'sell': 16259.38, 'symbol': '$'}, 'BRL': {'15m': 65429.17, 'last': 65429.17, 'buy': 65429.17, 'sell': 65429.17, 'symbol': 'R$'}, 'CAD': {'15m': 15286.12, 'last': 15286.12, 'buy': 15286.12, 'sell': 15286.12, 'symbol': '$'}, 'CHF': {'15m': 10601.87, 'last': 10601.87, 'buy': 10601.87, 'sell': 10601.87, 'symbol': 'CHF'}, 'CLP': {'15m': 9233305.46, 'last': 9233305.46, 'buy': 9233305.46, 'sell': 9233305.46, 'symbol': '$'}, 'CNY': {'15m': 80557.12, 'last': 80557.12, 'buy': 80557.12, 'sell': 80557.12, 'symbol': '¥'}, 'DKK': {'15m': 73476.43, 'last': 73476.43, 'buy': 73476.43, 'sell': 73476.43, 'symbol': 'kr'}, 'EUR': {'15m': 9889.45, 'last': 9889.45, 'buy': 9889.45, 'sell': 9889.45, 'symbol': '€'}, 'GBP': {'15m': 8894.18, 'last': 8894.18, 'buy': 8894.18, 'sell': 8894.18, 'symbol': '£'}, 'HKD': {'15m': 90228.86, 'last': 90228.86, 'buy': 90228.86, 'sell': 90228.86, 'symbol': '$'}, 'INR': {'15m': 872330.17, 'last': 872330.17, 'buy': 872330.17, 'sell': 872330.17, 'symbol': '₹'}, 'ISK': {'15m': 1604622.86, 'last': 1604622.86, 'buy': 1604622.86, 'sell': 1604622.86, 'symbol': 'kr'}, 'JPY': {'15m': 1232956.69, 'last': 1232956.69, 'buy': 1232956.69, 'sell': 1232956.69, 'symbol': '¥'}, 'KRW': {'15m': 13879877.15,
'last': 13879877.15, 'buy': 13879877.15, 'sell': 13879877.15, 'symbol': '₩'}, 'NZD': {'15m': 17783.33, 'last': 17783.33, 'buy': 17783.33, 'sell': 17783.33, 'symbol': '$'}, 'PLN': {'15m': 43580.83, 'last': 43580.83, 'buy': 43580.83, 'sell': 43580.83, 'symbol': 'zł'}, 'RUB': {'15m': 871068.18, 'last': 871068.18, 'buy': 871068.18, 'sell': 871068.18, 'symbol': 'RUB'}, 'SEK': {'15m': 102560.0, 'last': 102560.0, 'buy': 102560.0, 'sell': 102560.0, 'symbol': 'kr'}, 'SGD': {'15m': 15968.11, 'last': 15968.11, 'buy': 15968.11, 'sell': 15968.11, 'symbol': '$'}, 'THB': {'15m': 367195.68, 'last': 367195.68, 'buy': 367195.68, 'sell': 367195.68, 'symbol': '฿'}, 'TRY': {'15m': 85371.11, 'last': 85371.11, 'buy': 85371.11, 'sell': 85371.11, 'symbol': '₺'}, 'TWD': {'15m': 342299.36, 'last': 342299.36, 'buy': 342299.36, 'sell': 342299.36, 'symbol': 'NT$'}}

D:\Python38\envs\streaming_dev>d:/Python38/envs/streaming_dev/Scripts/activate.bat

(streaming_dev) D:\Python38\envs\streaming_dev>

So it looks like VS Code's debug console terminal supports UTF-8 or is in UTF-8 mode.

But, if I execute the script in VS Code in normal mode (not debug mode), my script terminates due to the RuntimeError: Event loop is closed exception exception:

Microsoft Windows [Version 10.0.17763.1397]
(c) 2018 Microsoft Corporation. All rights reserved.


D:\Python38\envs\streaming_dev>d:/Python38/envs/streaming_dev/Scripts/activate.bat

(streaming_dev) D:\Python38\envs\streaming_dev>d:/Python38/envs/streaming_dev/Scripts/python.exe d:/Python38/envs/streaming_dev/blockchain_demo.py
Job "Link.transfer (trigger: interval[0:00:01], next run at: 2020-08-23 11:53:40 EDT)" raised an exception
Traceback (most recent call last):
  File "d:\Python38\envs\streaming_dev\lib\site-packages\apscheduler\executors\base.py", line 125, in run_job
    retval = job.func(*job.args, **job.kwargs)
  File "d:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 227, in transfer
    asyncio.run(self._run())
  File "D:\Python38\lib\asyncio\runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "D:\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
    return future.result()
  File "d:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 306, in _run
    await asyncio.gather(*outlet_tasks)
  File "d:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 296, in outlet_task
    raise e
  File "d:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 291, in outlet_task
    await outlet._push(records_copy, update)
  File "d:\Python38\envs\streaming_dev\lib\site-packages\databay\outlet.py", line 37, in _push
    rv = await self.push(records, update)
  File "d:\Python38\envs\streaming_dev\lib\site-packages\databay\outlets\print_outlet.py", line 37, in push
    print(f'{update}{body}')
  File "D:\Python38\lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u20b9' in position 1120: character maps to <undefined>
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001C74A5D4310>
Traceback (most recent call last):
  File "D:\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

(streaming_dev) D:\Python38\envs\streaming_dev>

I tried to set cmder's encoding to support utf-8 via DOS's chcp command, but didn't work:

D:\Python38\envs\streaming_dev
(streaming_dev) λ CHCP 65001
Active code page: 65001

D:\Python38\envs\streaming_dev
(streaming_dev) λ python blockchain_demo.py
Job "Link.transfer (trigger: interval[0:00:01], next run at: 2020-08-23 11:47:02 EDT)" raised an exception
Traceback (most recent call last):
  File "D:\Python38\envs\streaming_dev\lib\site-packages\apscheduler\executors\base.py", line 125, in run_job
    retval = job.func(*job.args, **job.kwargs)
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 227, in transfer
    asyncio.run(self._run())
  File "D:\Python38\lib\asyncio\runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "D:\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
    return future.result()
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 306, in _run
    await asyncio.gather(*outlet_tasks)
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 296, in outlet_task
    raise e
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\link.py", line 291, in outlet_task
    await outlet._push(records_copy, update)
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\outlet.py", line 37, in _push
    rv = await self.push(records, update)
  File "D:\Python38\envs\streaming_dev\lib\site-packages\databay\outlets\print_outlet.py", line 37, in push
    print(f'{update}{body}')
  File "D:\Python38\lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u20b9' in position 1124: character maps to <undefined>
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000023B23337310>
Traceback (most recent call last):
  File "D:\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

D:\Python38\envs\streaming_dev
(streaming_dev) λ

@pybokeh
Copy link
Author

pybokeh commented Aug 23, 2020

@Voyz
I added the different logging line (logging.getLogger('databay').setLevel(logging.DEBUG)) to my blockchain_demo.py file and now the CP1252 encoding exception isn't being revealed or raised:

D:\Python38\envs\streaming_dev
(streaming_dev) λ python -m pdb blockchain_demo.py
> d:\python38\envs\streaming_dev\blockchain_demo.py(2)<module>()
-> import datetime
(Pdb) c
2020-08-23 12:04:58.198|I| Added link: Link(name:'', inlets:[HttpInlet(url=https://blockchain.info/ticker)], outlets:[PrintOutlet()], interval:0:00:01) (databay.BasePlanner)
2020-08-23 12:04:58.198|I| Starting APSPlanner(threads:30) (databay.BasePlanner)
> d:\python38\envs\streaming_dev\lib\site-packages\databay\planners\aps_planner.py(134)_start_planner()
-> self._scheduler.start()
(Pdb) c
2020-08-23 12:05:04.200|D| 0 transfer (databay.Link)
2020-08-23 12:05:04.201|I| 0 pulling https://blockchain.info/ticker (databay.HttpInlet)
2020-08-23 12:05:04.543|I| 0 received https://blockchain.info/ticker (databay.HttpInlet)
2020-08-23 12:05:04.553|I| Shutting down APSPlanner(threads:30) (databay.BasePlanner)
The program finished and will be restarted
> d:\python38\envs\streaming_dev\blockchain_demo.py(2)<module>()
-> import datetime
(Pdb) c
2020-08-23 12:05:07.967|I| Added link: Link(name:'', inlets:[HttpInlet(url=https://blockchain.info/ticker)], outlets:[PrintOutlet()], interval:0:00:01) (databay.BasePlanner)
2020-08-23 12:05:07.968|I| Starting APSPlanner(threads:30) (databay.BasePlanner)
> d:\python38\envs\streaming_dev\lib\site-packages\databay\planners\aps_planner.py(134)_start_planner()
-> self._scheduler.start()
(Pdb) c
2020-08-23 12:05:10.968|D| 0 transfer (databay.Link)
2020-08-23 12:05:10.969|I| 0 pulling https://blockchain.info/ticker (databay.HttpInlet)
2020-08-23 12:05:11.205|I| 0 received https://blockchain.info/ticker (databay.HttpInlet)
2020-08-23 12:05:11.208|I| Shutting down APSPlanner(threads:30) (databay.BasePlanner)
The program finished and will be restarted
> d:\python38\envs\streaming_dev\blockchain_demo.py(2)<module>()
-> import datetime
(Pdb) c
2020-08-23 12:05:12.561|I| Added link: Link(name:'', inlets:[HttpInlet(url=https://blockchain.info/ticker)], outlets:[PrintOutlet()], interval:0:00:01) (databay.BasePlanner)
2020-08-23 12:05:12.562|I| Starting APSPlanner(threads:30) (databay.BasePlanner)
> d:\python38\envs\streaming_dev\lib\site-packages\databay\planners\aps_planner.py(134)_start_planner()
-> self._scheduler.start()
(Pdb) c
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000020DD3B98280>
Traceback (most recent call last):
  File "D:\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000020DD3B98280>
Traceback (most recent call last):
  File "D:\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "D:\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "D:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "D:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
2020-08-23 12:05:14.582|D| 0 transfer (databay.Link)
2020-08-23 12:05:14.583|I| 0 pulling https://blockchain.info/ticker (databay.HttpInlet)
2020-08-23 12:05:14.959|I| 0 received https://blockchain.info/ticker (databay.HttpInlet)
2020-08-23 12:05:14.963|I| Shutting down APSPlanner(threads:30) (databay.BasePlanner)
The program finished and will be restarted
> d:\python38\envs\streaming_dev\blockchain_demo.py(2)<module>()
-> import datetime
(Pdb)

@Voyz
Copy link
Owner

Voyz commented Aug 23, 2020

That's fantastic info! It's the ₹ (Indian rupee) character (\u20b9) that seems to break the print. The response from that URL indeed contains that character. I find it hard to understand why does it break the execution only in some cases, but you must be right - the debugging mode sets different UTF encoding. That's a really good lead for me to follow though, so cheers!

Just to double check, could you give it a shot with this URL instead: https://jsonplaceholder.typicode.com/todos/1?

Your further tests showcased that there is something wrong with exception logging in APSPlanner. We only started seeing this message thanks for re-enabling APS's logger. In its design, APSPlanner should handle APS's exceptions logging, which clearly wasn't happening. Even more so, when you enable full DEBUG logging on Databay the exceptions from APS are hidden and not logged. This is clearly my mistake and I'll find a way to fix it ASAP. Great job helping me uncover this oversight 👍 I feel we dig through a good deal of little problems in this issue case.

For now, please run your code with:

logging.getLogger('apscheduler.executors').setLevel(logging.DEBUG)

and without:

logging.getLogger('databay').setLevel(logging.DEBUG)

Also, I'll again bring up my theory that your code doesn't stop working due to the Event loop... exception - in all cases it was thrown after the UnicodeEncodingError, ie. when the execution stops within a thread. Having read the sources you posted at the beginning about the Event loop... I would say it's safe to assume we should add the following to config.py:

import sys
import asyncio

if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

This will also clear up the error messages and make it easier to debug the unicode problem.

@Voyz
Copy link
Owner

Voyz commented Aug 23, 2020

Here seem to be some first clues for handling that Unicode error:

https://stackoverflow.com/a/16120218/3508719

if sys.stdout.encoding != 'cp850':
  sys.stdout = codecs.getwriter('cp850')(sys.stdout.buffer, 'strict')
if sys.stderr.encoding != 'cp850':
  sys.stderr = codecs.getwriter('cp850')(sys.stderr.buffer, 'strict')

and another one here:

https://stackoverflow.com/questions/878972/windows-cmd-encoding-change-causes-python-crash/3259271

chcp 65001
set PYTHONIOENCODING=utf-8
python example.py

@pybokeh
Copy link
Author

pybokeh commented Aug 24, 2020

@Voyz Well good news! Finally, got the blockchain_demo.py working.

Added:

import sys
import asyncio

if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

to the top of my local copy of config.py

and then at the terminal, executed:

chcp 65001
set PYTHONIOENCODING=utf-8

Then executed the blockchain_demo.py:

D:\Python38\envs\streaming_dev
(streaming_dev) λ python -m pdb blockchain_demo.py
> d:\python38\envs\streaming_dev\blockchain_demo.py(2)<module>()
-> import datetime
(Pdb) c
> d:\python38\envs\streaming_dev\lib\site-packages\databay\planners\aps_planner.py(134)_start_planner()
-> self._scheduler.start()
(Pdb) c
{'USD': {'15m': 11616.04, 'last': 11616.04, 'buy': 11616.04, 'sell': 11616.04, 'symbol': '$'}, 'AUD': {'15m': 16205.74, 'last': 16205.74, 'buy': 16205.74, 'sell': 16205.74, 'symbol': '$'}, 'BRL': {'15m': 65301.28, 'last': 65301.28, 'buy': 65301.28, 'sell': 65301.28, 'symbol': 'R$'}, 'CAD': {'15m': 15303.79, 'last': 15303.79, 'buy': 15303.79, 'sell': 15303.79, 'symbol': '$'}, 'CHF': {'15m': 10588.28, 'last': 10588.28, 'buy': 10588.28, 'sell': 10588.28, 'symbol': 'CHF'}, 'CLP': {'15m': 9212683.9, 'last': 9212683.9, 'buy': 9212683.9, 'sell': 9212683.9, 'symbol': '$'}, 'CNY': {'15m': 80377.21, 'last': 80377.21, 'buy': 80377.21, 'sell': 80377.21, 'symbol': '¥'}, 'DKK': {'15m': 73255.41, 'last': 73255.41, 'buy': 73255.41, 'sell': 73255.41, 'symbol': 'kr'}, 'EUR': {'15m': 9864.6, 'last': 9864.6, 'buy': 9864.6, 'sell': 9864.6, 'symbol': '€'}, 'GBP': {'15m': 8866.84, 'last': 8866.84, 'buy': 8866.84, 'sell': 8866.84, 'symbol': '£'}, 'HKD': {'15m': 90027.47, 'last': 90027.47, 'buy': 90027.47, 'sell': 90027.47, 'symbol': '$'}, 'INR': {'15m': 870356.18, 'last': 870356.18, 'buy': 870356.18, 'sell': 870356.18, 'symbol': '₹'}, 'ISK': {'15m': 1601038.9, 'last': 1601038.9, 'buy': 1601038.9, 'sell': 1601038.9, 'symbol': 'kr'}, 'JPY': {'15m': 1231929.44, 'last': 1231929.44, 'buy': 1231929.44, 'sell': 1231929.44, 'symbol': '¥'}, 'KRW': {'15m': 13843360.88, 'last': 13843360.88, 'buy': 13843360.88, 'sell': 13843360.88, 'symbol': '₩'}, 'NZD': {'15m': 17753.7, 'last': 17753.7, 'buy': 17753.7, 'sell': 17753.7, 'symbol': '$'}, 'PLN': {'15m': 43410.94, 'last': 43410.94, 'buy': 43410.94, 'sell': 43410.94, 'symbol': 'zł'}, 'RUB': {'15m': 868955.96, 'last': 868955.96, 'buy': 868955.96, 'sell': 868955.96, 'symbol': 'RUB'}, 'SEK': {'15m': 102017.68, 'last': 102017.68, 'buy': 102017.68, 'sell': 102017.68, 'symbol': 'kr'}, 'SGD': {'15m': 15933.58, 'last': 15933.58, 'buy': 15933.58, 'sell': 15933.58, 'symbol': '$'}, 'THB': {'15m': 366042.0, 'last': 366042.0, 'buy': 366042.0, 'sell': 366042.0, 'symbol': '฿'}, 'TRY': {'15m': 85021.27, 'last': 85021.27, 'buy': 85021.27, 'sell': 85021.27, 'symbol': '₺'}, 'TWD': {'15m': 341550.96, 'last': 341550.96, 'buy': 341550.96, 'sell': 341550.96, 'symbol': 'NT$'}}
{'USD': {'15m': 11616.04, 'last': 11616.04, 'buy': 11616.04, 'sell': 11616.04, 'symbol': '$'}, 'AUD': {'15m': 16205.74, 'last': 16205.74, 'buy': 16205.74, 'sell': 16205.74, 'symbol': '$'}, 'BRL': {'15m': 65301.28, 'last': 65301.28, 'buy': 65301.28, 'sell': 65301.28, 'symbol': 'R$'}, 'CAD': {'15m': 15303.79, 'last': 15303.79, 'buy': 15303.79, 'sell': 15303.79, 'symbol': '$'}, 'CHF': {'15m': 10588.28, 'last': 10588.28, 'buy': 10588.28, 'sell': 10588.28, 'symbol': 'CHF'}, 'CLP': {'15m': 9212683.9, 'last': 9212683.9, 'buy': 9212683.9, 'sell': 9212683.9, 'symbol': '$'}, 'CNY': {'15m': 80377.21, 'last': 80377.21, 'buy': 80377.21, 'sell': 80377.21, 'symbol': '¥'}, 'DKK': {'15m': 73255.41, 'last': 73255.41, 'buy': 73255.41, 'sell': 73255.41, 'symbol': 'kr'}, 'EUR': {'15m': 9864.6, 'last': 9864.6, 'buy': 9864.6, 'sell': 9864.6, 'symbol': '€'}, 'GBP': {'15m': 8866.84, 'last': 8866.84, 'buy': 8866.84, 'sell': 8866.84, 'symbol': '£'}, 'HKD': {'15m': 90027.47, 'last': 90027.47, 'buy': 90027.47, 'sell': 90027.47, 'symbol': '$'}, 'INR': {'15m': 870356.18, 'last': 870356.18, 'buy': 870356.18, 'sell': 870356.18, 'symbol': '₹'}, 'ISK': {'15m': 1601038.9, 'last': 1601038.9, 'buy': 1601038.9, 'sell': 1601038.9, 'symbol': 'kr'}, 'JPY': {'15m': 1231929.44, 'last': 1231929.44, 'buy': 1231929.44, 'sell': 1231929.44, 'symbol': '¥'}, 'KRW': {'15m': 13843360.88, 'last': 13843360.88, 'buy': 13843360.88, 'sell': 13843360.88, 'symbol': '₩'}, 'NZD': {'15m': 17753.7, 'last': 17753.7, 'buy': 17753.7, 'sell': 17753.7, 'symbol': '$'}, 'PLN': {'15m': 43410.94, 'last': 43410.94, 'buy': 43410.94, 'sell': 43410.94, 'symbol': 'zł'}, 'RUB': {'15m': 868955.96, 'last': 868955.96, 'buy': 868955.96, 'sell': 868955.96, 'symbol': 'RUB'}, 'SEK': {'15m': 102017.68, 'last': 102017.68, 'buy': 102017.68, 'sell': 102017.68, 'symbol': 'kr'}, 'SGD': {'15m': 15933.58, 'last': 15933.58, 'buy': 15933.58, 'sell': 15933.58, 'symbol': '$'}, 'THB': {'15m': 366042.0, 'last': 366042.0, 'buy': 366042.0, 'sell': 366042.0, 'symbol': '฿'}, 'TRY': {'15m': 85021.27, 'last': 85021.27, 'buy': 85021.27, 'sell': 85021.27, 'symbol': '₺'}, 'TWD': {'15m': 341550.96, 'last': 341550.96, 'buy': 341550.96, 'sell': 341550.96, 'symbol': 'NT$'}}
{'USD': {'15m': 11616.04, 'last': 11616.04, 'buy': 11616.04, 'sell': 11616.04, 'symbol': '$'}, 'AUD': {'15m': 16205.74, 'last': 16205.74, 'buy': 16205.74, 'sell': 16205.74, 'symbol': '$'}, 'BRL': {'15m': 65301.28, 'last': 65301.28, 'buy': 65301.28, 'sell': 65301.28, 'symbol': 'R$'}, 'CAD': {'15m': 15303.79, 'last': 15303.79, 'buy': 15303.79, 'sell': 15303.79, 'symbol': '$'}, 'CHF': {'15m': 10588.28, 'last': 10588.28, 'buy': 10588.28, 'sell': 10588.28, 'symbol': 'CHF'}, 'CLP': {'15m': 9212683.9, 'last': 9212683.9, 'buy': 9212683.9, 'sell': 9212683.9, 'symbol': '$'}, 'CNY': {'15m': 80377.21, 'last': 80377.21, 'buy': 80377.21, 'sell': 80377.21, 'symbol': '¥'}, 'DKK': {'15m': 73255.41, 'last': 73255.41, 'buy': 73255.41, 'sell': 73255.41, 'symbol': 'kr'}, 'EUR': {'15m': 9864.6, 'last': 9864.6, 'buy': 9864.6, 'sell': 9864.6, 'symbol': '€'}, 'GBP': {'15m': 8866.84, 'last': 8866.84, 'buy': 8866.84, 'sell': 8866.84, 'symbol': '£'}, 'HKD': {'15m': 90027.47, 'last': 90027.47, 'buy': 90027.47, 'sell': 90027.47, 'symbol': '$'}, 'INR': {'15m': 870356.18, 'last': 870356.18, 'buy': 870356.18, 'sell': 870356.18, 'symbol': '₹'}, 'ISK': {'15m': 1601038.9, 'last': 1601038.9, 'buy': 1601038.9, 'sell': 1601038.9, 'symbol': 'kr'}, 'JPY': {'15m': 1231929.44, 'last': 1231929.44, 'buy': 1231929.44, 'sell': 1231929.44, 'symbol': '¥'}, 'KRW': {'15m': 13843360.88, 'last': 13843360.88, 'buy': 13843360.88, 'sell': 13843360.88, 'symbol': '₩'}, 'NZD': {'15m': 17753.7, 'last': 17753.7, 'buy': 17753.7, 'sell': 17753.7, 'symbol': '$'}, 'PLN': {'15m': 43410.94, 'last': 43410.94, 'buy': 43410.94, 'sell': 43410.94, 'symbol': 'zł'}, 'RUB': {'15m': 868955.96, 'last': 868955.96, 'buy': 868955.96, 'sell': 868955.96, 'symbol': 'RUB'}, 'SEK': {'15m': 102017.68, 'last': 102017.68, 'buy': 102017.68, 'sell': 102017.68, 'symbol': 'kr'}, 'SGD': {'15m': 15933.58, 'last': 15933.58, 'buy': 15933.58, 'sell': 15933.58, 'symbol': '$'}, 'THB': {'15m': 366042.0, 'last': 366042.0, 'buy': 366042.0, 'sell': 366042.0, 'symbol': '฿'}, 'TRY': {'15m': 85021.27, 'last': 85021.27, 'buy': 85021.27, 'sell': 85021.27, 'symbol': '₺'}, 'TWD': {'15m': 341550.96, 'last': 341550.96, 'buy': 341550.96, 'sell': 341550.96, 'symbol': 'NT$'}}
{'USD': {'15m': 11616.82, 'last': 11616.82, 'buy': 11616.82, 'sell': 11616.82, 'symbol': '$'}, 'AUD': {'15m': 16204.46, 'last': 16204.46, 'buy': 16204.46, 'sell': 16204.46, 'symbol': '$'}, 'BRL': {'15m': 65305.65, 'last': 65305.65, 'buy': 65305.65, 'sell': 65305.65, 'symbol': 'R$'}, 'CAD': {'15m': 15302.23, 'last': 15302.23, 'buy': 15302.23, 'sell': 15302.23, 'symbol': '$'}, 'CHF': {'15m': 10588.85, 'last': 10588.85, 'buy': 10588.85, 'sell': 10588.85, 'symbol': 'CHF'}, 'CLP': {'15m': 9213275.97, 'last': 9213275.97, 'buy': 9213275.97, 'sell': 9213275.97, 'symbol': '$'}, 'CNY': {'15m': 80382.58, 'last': 80382.58, 'buy': 80382.58, 'sell': 80382.58, 'symbol': '¥'}, 'DKK': {'15m': 73286.28, 'last': 73286.28, 'buy': 73286.28, 'sell': 73286.28, 'symbol': 'kr'}, 'EUR': {'15m': 9865.33, 'last': 9865.33, 'buy': 9865.33, 'sell': 9865.33, 'symbol': '€'}, 'GBP': {'15m': 8868.58, 'last': 8868.58, 'buy': 8868.58, 'sell': 8868.58, 'symbol': '£'}, 'HKD': {'15m': 90033.14, 'last': 90033.14, 'buy': 90033.14, 'sell': 90033.14, 'symbol': '$'}, 'INR': {'15m': 870414.34, 'last': 870414.34, 'buy': 870414.34, 'sell': 870414.34, 'symbol': '₹'}, 'ISK': {'15m': 1601145.91, 'last': 1601145.91, 'buy': 1601145.91, 'sell': 1601145.91, 'symbol': 'kr'}, 'JPY': {'15m': 1231925.29, 'last': 1231925.29, 'buy': 1231925.29, 'sell': 1231925.29, 'symbol': '¥'}, 'KRW': {'15m': 13844286.07, 'last': 13844286.07, 'buy': 13844286.07, 'sell': 13844286.07, 'symbol': '₩'}, 'NZD': {'15m': 17752.53, 'last': 17752.53, 'buy': 17752.53, 'sell': 17752.53, 'symbol': '$'}, 'PLN': {'15m': 43424.56, 'last': 43424.56, 'buy': 43424.56, 'sell': 43424.56, 'symbol': 'zł'}, 'RUB': {'15m': 869014.03, 'last': 869014.03, 'buy': 869014.03, 'sell': 869014.03, 'symbol': 'RUB'}, 'SEK': {'15m': 101821.42, 'last': 101821.42, 'buy': 101821.42, 'sell': 101821.42, 'symbol': 'kr'}, 'SGD': {'15m': 15935.16, 'last': 15935.16, 'buy': 15935.16, 'sell': 15935.16, 'symbol': '$'}, 'THB': {'15m': 366204.5, 'last': 366204.5, 'buy': 366204.5, 'sell': 366204.5, 'symbol': '฿'}, 'TRY': {'15m': 85170.95, 'last': 85170.95, 'buy': 85170.95, 'sell': 85170.95, 'symbol': '₺'}, 'TWD': {'15m': 341573.79, 'last': 341573.79, 'buy': 341573.79, 'sell': 341573.79, 'symbol': 'NT$'}}
{'USD': {'15m': 11616.04, 'last': 11616.04, 'buy': 11616.04, 'sell': 11616.04, 'symbol': '$'}, 'AUD': {'15m': 16205.74, 'last': 16205.74, 'buy': 16205.74, 'sell': 16205.74, 'symbol': '$'}, 'BRL': {'15m': 65301.28, 'last': 65301.28, 'buy': 65301.28, 'sell': 65301.28, 'symbol': 'R$'}, 'CAD': {'15m': 15303.79, 'last': 15303.79, 'buy': 15303.79, 'sell': 15303.79, 'symbol': '$'}, 'CHF': {'15m': 10588.28, 'last': 10588.28, 'buy': 10588.28, 'sell': 10588.28, 'symbol': 'CHF'}, 'CLP': {'15m': 9212683.9, 'last': 9212683.9, 'buy': 9212683.9, 'sell': 9212683.9, 'symbol': '$'}, 'CNY': {'15m': 80377.21, 'last': 80377.21, 'buy': 80377.21, 'sell': 80377.21, 'symbol': '¥'}, 'DKK': {'15m': 73255.41, 'last': 73255.41, 'buy': 73255.41, 'sell': 73255.41, 'symbol': 'kr'}, 'EUR': {'15m': 9864.6, 'last': 9864.6, 'buy': 9864.6, 'sell': 9864.6, 'symbol': '€'}, 'GBP': {'15m': 8866.84, 'last': 8866.84, 'buy': 8866.84, 'sell': 8866.84, 'symbol': '£'}, 'HKD': {'15m': 90027.47, 'last': 90027.47, 'buy': 90027.47, 'sell': 90027.47, 'symbol': '$'}, 'INR': {'15m': 870356.18, 'last': 870356.18, 'buy': 870356.18, 'sell': 870356.18, 'symbol': '₹'}, 'ISK': {'15m': 1601038.9, 'last': 1601038.9, 'buy': 1601038.9, 'sell': 1601038.9, 'symbol': 'kr'}, 'JPY': {'15m': 1231929.44, 'last': 1231929.44, 'buy': 1231929.44, 'sell': 1231929.44, 'symbol': '¥'}, 'KRW': {'15m': 13843360.88, 'last': 13843360.88, 'buy': 13843360.88, 'sell': 13843360.88, 'symbol': '₩'}, 'NZD': {'15m': 17753.7, 'last': 17753.7, 'buy': 17753.7, 'sell': 17753.7, 'symbol': '$'}, 'PLN': {'15m': 43410.94, 'last': 43410.94, 'buy': 43410.94, 'sell': 43410.94, 'symbol': 'zł'}, 'RUB': {'15m': 868955.96, 'last': 868955.96, 'buy': 868955.96, 'sell': 868955.96, 'symbol': 'RUB'}, 'SEK': {'15m': 102017.68, 'last': 102017.68, 'buy': 102017.68, 'sell': 102017.68, 'symbol': 'kr'}, 'SGD': {'15m': 15933.58, 'last': 15933.58, 'buy': 15933.58, 'sell': 15933.58, 'symbol': '$'}, 'THB': {'15m': 366042.0, 'last': 366042.0, 'buy': 366042.0, 'sell': 366042.0, 'symbol': '฿'}, 'TRY': {'15m': 85021.27, 'last': 85021.27, 'buy': 85021.27, 'sell': 85021.27, 'symbol': '₺'}, 'TWD': {'15m': 341550.96, 'last': 341550.96, 'buy': 341550.96, 'sell': 341550.96, 'symbol': 'NT$'}}
{'USD': {'15m': 11616.04, 'last': 11616.04, 'buy': 11616.04, 'sell': 11616.04, 'symbol': '$'}, 'AUD': {'15m': 16205.74, 'last': 16205.74, 'buy': 16205.74, 'sell': 16205.74, 'symbol': '$'}, 'BRL': {'15m': 65301.28, 'last': 65301.28, 'buy': 65301.28, 'sell': 65301.28, 'symbol': 'R$'}, 'CAD': {'15m': 15303.79, 'last': 15303.79, 'buy': 15303.79, 'sell': 15303.79, 'symbol': '$'}, 'CHF': {'15m': 10588.28, 'last': 10588.28, 'buy': 10588.28, 'sell': 10588.28, 'symbol': 'CHF'}, 'CLP': {'15m': 9212683.9, 'last': 9212683.9, 'buy': 9212683.9, 'sell': 9212683.9, 'symbol': '$'}, 'CNY': {'15m': 80377.21, 'last': 80377.21, 'buy': 80377.21, 'sell': 80377.21, 'symbol': '¥'}, 'DKK': {'15m': 73255.41, 'last': 73255.41, 'buy': 73255.41, 'sell': 73255.41, 'symbol': 'kr'}, 'EUR': {'15m': 9864.6, 'last': 9864.6, 'buy': 9864.6, 'sell': 9864.6, 'symbol': '€'}, 'GBP': {'15m': 8866.84, 'last': 8866.84, 'buy': 8866.84, 'sell': 8866.84, 'symbol': '£'}, 'HKD': {'15m': 90027.47, 'last': 90027.47, 'buy': 90027.47, 'sell': 90027.47, 'symbol': '$'}, 'INR': {'15m': 870356.18, 'last': 870356.18, 'buy': 870356.18, 'sell': 870356.18, 'symbol': '₹'}, 'ISK': {'15m': 1601038.9, 'last': 1601038.9, 'buy': 1601038.9, 'sell': 1601038.9, 'symbol': 'kr'}, 'JPY': {'15m': 1231929.44, 'last': 1231929.44, 'buy': 1231929.44, 'sell': 1231929.44, 'symbol': '¥'}, 'KRW': {'15m': 13843360.88, 'last': 13843360.88, 'buy': 13843360.88, 'sell': 13843360.88, 'symbol': '₩'}, 'NZD': {'15m': 17753.7, 'last': 17753.7, 'buy': 17753.7, 'sell': 17753.7, 'symbol': '$'}, 'PLN': {'15m': 43410.94, 'last': 43410.94, 'buy': 43410.94, 'sell': 43410.94, 'symbol': 'zł'}, 'RUB': {'15m': 868955.96, 'last': 868955.96, 'buy': 868955.96, 'sell': 868955.96, 'symbol': 'RUB'}, 'SEK': {'15m': 102017.68, 'last': 102017.68, 'buy': 102017.68, 'sell': 102017.68, 'symbol': 'kr'}, 'SGD': {'15m': 15933.58, 'last': 15933.58, 'buy': 15933.58, 'sell': 15933.58, 'symbol': '$'}, 'THB': {'15m': 366042.0, 'last': 366042.0, 'buy': 366042.0, 'sell': 366042.0, 'symbol': '฿'}, 'TRY': {'15m': 85021.27, 'last': 85021.27, 'buy': 85021.27, 'sell': 85021.27, 'symbol': '₺'}, 'TWD': {'15m': 341550.96, 'last': 341550.96, 'buy': 341550.96, 'sell': 341550.96, 'symbol': 'NT$'}}
{'USD': {'15m': 11616.04, 'last': 11616.04, 'buy': 11616.04, 'sell': 11616.04, 'symbol': '$'}, 'AUD': {'15m': 16205.74, 'last': 16205.74, 'buy': 16205.74, 'sell': 16205.74, 'symbol': '$'}, 'BRL': {'15m': 65301.28, 'last': 65301.28, 'buy': 65301.28, 'sell': 65301.28, 'symbol': 'R$'}, 'CAD': {'15m': 15303.79, 'last': 15303.79, 'buy': 15303.79, 'sell': 15303.79, 'symbol': '$'}, 'CHF': {'15m': 10588.28, 'last': 10588.28, 'buy': 10588.28, 'sell': 10588.28, 'symbol': 'CHF'}, 'CLP': {'15m': 9212683.9, 'last': 9212683.9, 'buy': 9212683.9, 'sell': 9212683.9, 'symbol': '$'}, 'CNY': {'15m': 80377.21, 'last': 80377.21, 'buy': 80377.21, 'sell': 80377.21, 'symbol': '¥'}, 'DKK': {'15m': 73255.41, 'last': 73255.41, 'buy': 73255.41, 'sell': 73255.41, 'symbol': 'kr'}, 'EUR': {'15m': 9864.6, 'last': 9864.6, 'buy': 9864.6, 'sell': 9864.6, 'symbol': '€'}, 'GBP': {'15m': 8866.84, 'last': 8866.84, 'buy': 8866.84, 'sell': 8866.84, 'symbol': '£'}, 'HKD': {'15m': 90027.47, 'last': 90027.47, 'buy': 90027.47, 'sell': 90027.47, 'symbol': '$'}, 'INR': {'15m': 870356.18, 'last': 870356.18, 'buy': 870356.18, 'sell': 870356.18, 'symbol': '₹'}, 'ISK': {'15m': 1601038.9, 'last': 1601038.9, 'buy': 1601038.9, 'sell': 1601038.9, 'symbol': 'kr'}, 'JPY': {'15m': 1231929.44, 'last': 1231929.44, 'buy': 1231929.44, 'sell': 1231929.44, 'symbol': '¥'}, 'KRW': {'15m': 13843360.88, 'last': 13843360.88, 'buy': 13843360.88, 'sell': 13843360.88, 'symbol': '₩'}, 'NZD': {'15m': 17753.7, 'last': 17753.7, 'buy': 17753.7, 'sell': 17753.7, 'symbol': '$'}, 'PLN': {'15m': 43410.94, 'last': 43410.94, 'buy': 43410.94, 'sell': 43410.94, 'symbol': 'zł'}, 'RUB': {'15m': 868955.96, 'last': 868955.96, 'buy': 868955.96, 'sell': 868955.96, 'symbol': 'RUB'}, 'SEK': {'15m': 102017.68, 'last': 102017.68, 'buy': 102017.68, 'sell': 102017.68, 'symbol': 'kr'}, 'SGD': {'15m': 15933.58, 'last': 15933.58, 'buy': 15933.58, 'sell': 15933.58, 'symbol': '$'}, 'THB': {'15m': 366042.0, 'last': 366042.0, 'buy': 366042.0, 'sell': 366042.0, 'symbol': '฿'}, 'TRY': {'15m': 85021.27, 'last': 85021.27, 'buy': 85021.27, 'sell': 85021.27, 'symbol': '₺'}, 'TWD': {'15m': 341550.96, 'last': 341550.96, 'buy': 341550.96, 'sell': 341550.96, 'symbol': 'NT$'}}

Program interrupted. (Use 'cont' to resume).
> d:\python38\lib\threading.py(309)wait()
-> return gotit
(Pdb)

EDIT:
It appears you don't need to issue the chcp 65001 command, just setting the PYTHONIOENCODING environment variable to utf-8 took care of the encoding issue.

@Voyz
Copy link
Owner

Voyz commented Aug 24, 2020

That's fantastic news!! I'm happy we managed to find the culprit (and a few others along the lines!). And most importantly I'm happy you can run that example finally 😊 Thanks for doing all these tests mate, that's been a massive help!

I'll create a PR with the Event loop... fix, while the unicode encoding workaround I'll put into a Troubleshooting section (which doesn't yet exist). I'll do more research into the PYTHONENCODING and why and when it is needed. Any idea if you machine had this set to something different for some reason?

I'm also looking into fixing the exception logging that has failed you here and prevented you from seeing the right message straight away.

I'll keep you posted on updates on these issues. In the meantime I'm modifying the title of this Issue so that it's easier to find info on our hunt for the Unicode error, in case others stumble upon it in the future too.

Well done and thanks a lot!

@Voyz Voyz changed the title asyncio-related error when using databay with Windows 10 - RuntimeError: Event loop is closed Windows 10 - RuntimeError: Event loop is closed and UnicodeEncodeError: 'charmap' codec can't encode character Aug 24, 2020
@Voyz
Copy link
Owner

Voyz commented Aug 24, 2020

Sorry just realised you mentioned you'd like to contribute - would you like to introduce the PR with the Event loop... fix? I'm more than happy to do it otherwise, but just thought it would be great for you to have a contribution too, seeing you mentioned you'd like to do so. Either way is good for me 👍

@pybokeh
Copy link
Author

pybokeh commented Aug 24, 2020

@Voyz You're welcome! It was fun and rewarding for me to help in any way I can.

As for the PYTHONIOENCODING thing, I have no idea. I think it has to do with whenever things are being echoed or printed to standard output? or what about to file? I do want to test your other examples where we are sending output to file.

Thanks for asking me to do the PR. But, it's ok,, please do the PR yourself. I'm just glad to be able to help out.

@Voyz
Copy link
Owner

Voyz commented Aug 24, 2020

Either way I'm happy that it helped.

It seems like it would break for a file too. I'm also guessing that this possibly was also breaking the exceptions - although that's just a blind guess - so it could be both stdout and stderr that are affected by it. From what I read on the UnicodeEncodeError this should also cause problems if you write to a file. Easy way to verify it would be to run the following two snippets without that set PYTHONIOENCODING=utf-8 env variable (so the old way).

print('₹')

and

with open('unicode_test_file.txt', 'a') as f:
    f.write('₹')

Both should break as far as I understand. I'll let you know if I figure out why your setup might have had that set incorrectly. And I'd love to hear how it goes with other examples for you, so keep me posted 😊

Naturally, I'll do the PR, no worries - you helped out big time. Thanks for all the contribution towards fixing this problem!

@Voyz
Copy link
Owner

Voyz commented Aug 25, 2020

Good news - I managed to get to the bottom of this. There was indeed a bug in exception logging of APSPlanner, triggered by exceptions with a strange signature such as that of UnicodeEncodeError. My bad. Got that verified and fixed now.

Most importantly - I finally found a way to reproduce this error! And not without struggle - there's a million methods to fix it out there, just about none to reproduce it. Eventually, this is what was needed:

set PYTHONIOENCODING=windows-1252
set PYTHONLEGACYWINDOWSSTDIO=windows-1252

or alternatively in code:

sys.stdin.reconfigure(encoding='windows-1252')
sys.stdout.reconfigure(encoding='windows-1252')

Which would suggest that your machine had it set to windows-1252 (or something else?) by default. A good way to find out what's the answer is to run:

print(sys.stdin.encoding, sys.stdout.encoding)

Either way - happy I managed to reproduce what was happening on your end finally. Thanks for the patience once again! I'll update when the fixes are released.

@pybokeh
Copy link
Author

pybokeh commented Aug 25, 2020

@Voyz I found out what my problem was. I had looked at my local environment variables before, but overlooked that there is a PYTHONLEGACYWINDOWSSTDIO that was set to true. After removing this environment variable, rebooting my machine, now I can run your examples without having to set PYTHONIOENCODING environment variable. I am trying to recall the reasoning for why I had PYTHONLEGACYWINDOWSSTDIO environment variable set. I'm guessing it was due to when I was using older versions of Python and had encoding issues with the default Windows terminal back then. Official Python docs happen to have a page on the command line and it appears there was some kind of change beginning with Python 3.6 where that environment variable was no longer needed.

With no Python-related environment set and then executing print(sys.stdin.encoding, sys.stdout.encoding), I am getting utf-8 now.

@Voyz
Copy link
Owner

Voyz commented Aug 26, 2020

Fantastic you managed to figure this one out! Thanks for following up with the explanation - that explains everything. I nonetheless added a warning should someone have that encoding set incorrectly, as this may cause unexpected behaviour without being very verbose.

@Voyz Voyz closed this as completed in #6 Aug 27, 2020
Voyz added a commit that referenced this issue Aug 27, 2020
asyncio Event loop policy, UnicodeEncodeError and planners' exception handling (fixes #3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
2 participants