{"action":"opened","issue":{"url":"https://api.github.com/repos/harvimt/quamash/issues/23","labels_url":"https://api.github.com/repos/harvimt/quamash/issues/23/labels{/name}","comments_url":"https://api.github.com/repos/harvimt/quamash/issues/23/comments","events_url":"https://api.github.com/repos/harvimt/quamash/issues/23/events","html_url":"https://github.com/harvimt/quamash/issues/23","id":54410423,"number":23,"title":"Context Manager / set_event_loop & event loop policies","user":{"login":"harvimt","id":119106,"avatar_url":"https://avatars.githubusercontent.com/u/119106?v=3","gravatar_id":"","url":"https://api.github.com/users/harvimt","html_url":"https://github.com/harvimt","followers_url":"https://api.github.com/users/harvimt/followers","following_url":"https://api.github.com/users/harvimt/following{/other_user}","gists_url":"https://api.github.com/users/harvimt/gists{/gist_id}","starred_url":"https://api.github.com/users/harvimt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/harvimt/subscriptions","organizations_url":"https://api.github.com/users/harvimt/orgs","repos_url":"https://api.github.com/users/harvimt/repos","events_url":"https://api.github.com/users/harvimt/events{/privacy}","received_events_url":"https://api.github.com/users/harvimt/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/harvimt/quamash/labels/bug","name":"bug","color":"fc2929"},{"url":"https://api.github.com/repos/harvimt/quamash/labels/question","name":"question","color":"cc317c"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/harvimt/quamash/milestones/3","labels_url":"https://api.github.com/repos/harvimt/quamash/milestones/3/labels","id":936242,"number":3,"title":"future","description":null,"creator":{"login":"harvimt","id":119106,"avatar_url":"https://avatars.githubusercontent.com/u/119106?v=3","gravatar_id":"","url":"https://api.github.com/users/harvimt","html_url":"https://github.com/harvimt","followers_url":"https://api.github.com/users/harvimt/followers","following_url":"https://api.github.com/users/harvimt/following{/other_user}","gists_url":"https://api.github.com/users/harvimt/gists{/gist_id}","starred_url":"https://api.github.com/users/harvimt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/harvimt/subscriptions","organizations_url":"https://api.github.com/users/harvimt/orgs","repos_url":"https://api.github.com/users/harvimt/repos","events_url":"https://api.github.com/users/harvimt/events{/privacy}","received_events_url":"https://api.github.com/users/harvimt/received_events","type":"User","site_admin":false},"open_issues":1,"closed_issues":0,"state":"open","created_at":"2015-01-15T04:06:24Z","updated_at":"2015-01-15T04:06:24Z","due_on":null,"closed_at":null},"comments":0,"created_at":"2015-01-15T04:06:24Z","updated_at":"2015-01-15T04:06:24Z","closed_at":null,"body":"[Relevant Section of the PEP](https://www.python.org/dev/peps/pep-3156/#event-loop-policy-getting-and-setting-the-current-event-loop)\r\n\r\nThis i rambly, sorry.\r\n\r\nin bug #22 a user seemed to show confusion about the necessity of and proper place to set the event loop. The context manager sort of obscures all this. Additionally, it's not clear whether unsetting the event loop is particularly necessary. I'm struggling to understand how/why\r\n\r\nTo give some context, some parts of quamash pre-date quamash, namely `\\@easycallback` which was a helper I made to make working with QThreads easier, (but not easy enough, I still had to write \"twisted\" callback based code). I was mostly using QThreads for asyncio (like making http requests) anyway, so this worked ok. Executors use a context manager to call shutdown and it seemed event loops should to. At least custom ones, but after reading the PEP as it has evolved this is beginning to seem like a presumption about how event loops are used: set, use, reset to defaults. This doesn't seem to be how they're used at all, usually you use *one* event loop as sort of the master, and then you can go off and do work in the same thread, in a separate process, in a different thread, but have it all call back to the master event loop.\r\n\r\nSo several questions:\r\n\r\n1. Should the context manager be deprecated, it doesn't violate the PEP, but it's a feature unique (as far as I know) to Quamash.\r\n2. If we keep the context manager, since it is somewhat useful, should it be the preferred way to set the event loop?\r\n3. How often will people be using multiple event loops? (using one, then switching back and forth between which one is active). This seems to be an unusual use case. Not one that should be forbidden, but we don't need to work extra hard to make it easy.\r\n4. Should an event loop policy be implemented. Then the appropriate usage would be to set the event loop policy, instead of setting the event loop directly. This makes using different event loop implementations harder, (but is also not required usage, you could still set/get the event loop manually or use QEventLoop with the standard policy)\r\n5. A custom event loop policy has the possibility of making `QThreadExecutor`s more useful as you could run coroutines in them, with a per-thread event loop with less. Even more useful, the .execute could check if a coroutine or a regular function is being passed in, and a coroutine could be wrapped in asyncio.async()' (The policy would then need to manage thread affinity)\r\nsee: http://qt-project.org/doc/qt-4.8/threads-qobject.html (tricky but potentially useful)\r\n6. A custom event loop policy will likely lead to even more platform specific stuff, and is one more moving part that can go wrong. (well the baseclass will need to be different on windows & unix)\r\n\r\nExample code:\r\n\r\n```python\r\n\r\n@asyncio.coroutine\r\ndef async_job():\r\n     yield from asyncio.sleep(.1)\r\n\r\ndef threaded_job():\r\n    local_loop = asyncio.get_event_loop()  # with standard policy, this will raise an Exception\r\n    asyncio.async(async_job())\r\n    \r\n    local_loop.run_until_complete(async_job())\r\n\r\nasyncio.set_event_loop_policy(quamash.QEventLoopPolicy(app))\r\nloop = asyncio.get_event_loop()\r\nwith QThreadExecutor(5) as exec:\r\n   yield from loop.run_in_executor(exec, threaded_job)\r\n```\r\n\r\n"}}