Can uvicorn support windows?
I am develops in windows, and want to use uvicorn.
Certainly the latest version (0.2) should, as there's no platform-specific stuff in there.
I don't know if there's any issues or not prior to that (or with 0.2 running under gunicorn) but happy to hear of any issues if you're seeing them
I have try to run under windows, there some stuff want to modify:
uvloop no support; want to use the default loop;
Okay, that's easy enough to do: --loop asyncio tho we might want to detect windows or pypy, and choose our loop and parser policies accordingly.
See also https://github.com/MagicStack/uvloop/issues/14 and https://github.com/MagicStack/uvloop/pull/62
signals no support; disable UvicornWorker.init_signals and Server.set_signal_handlers
Okay, I've disable them in https://github.com/encode/uvicorn/pull/122
I've attempted to support catching Ctrl+C through signal.signal, but it's not clear to me if it's sufficient as implemented. (See https://stackoverflow.com/questions/24774980/why-cant-i-catch-sigint-when-asyncio-event-loop-is-running/24775107#24775107)
It's possible that we ought to start a new thread on windows specifically to catch signals.
Released as 0.2.10.
It'd be hugely helpful for anyone running on windows to try...
uvicorn app:app --loop asyncio
(Use the basic example app in the README to keep everything else simple)
And see if:
Hey @tomchristie, the installation on Windows fails because uvloop does not support Windows at the moment. Is there an option to install uvicorn without uvloop?
I found an ugly workaround of installing uvicorn with --no-dependencies and then installing every dependecy except uvloop manually.
Also worth noting that httptools requires a whole Visual Studio 2015 to build
I tested it on 64-bit Windows 10 Pro 1803 and Anaconda Python 3.6.5
Does it start up okay now and serve requests? (If not what output do you see?)
Yes, it works pretty well
Does it terminates okay on Ctrl+C events now? (What output do you see? Does nothing happen, or is it a clean termination, or is a python exception displayed?)
Yes, it terminates on Ctrl+C, not without an exception though:
(venv) C:\Users\ddkon\Projects\uvicorn-win-test>uvicorn app:App --loop asyncio
* Uvicorn running on http://127.0.0.1:8000 🦄 (Press CTRL+C to quit)
INFO: Started worker [10504]
INFO: 127.0.0.1 - "GET / HTTP/1.1" 200
INFO: 127.0.0.1 - "GET /favicon.ico HTTP/1.1" 200
INFO: 127.0.0.1 - "GET / HTTP/1.1" 200
INFO: 127.0.0.1 - "GET /favicon.ico HTTP/1.1" 200
INFO: 127.0.0.1 - "GET / HTTP/1.1" 200
INFO: 127.0.0.1 - "GET /favicon.ico HTTP/1.1" 200
INFO: 127.0.0.1 - "GET /what HTTP/1.1" 200
INFO: 127.0.0.1 - "GET /favicon.ico HTTP/1.1" 200
Traceback (most recent call last):
File "c:\users\ddkon\anaconda3\Lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "c:\users\ddkon\anaconda3\Lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Users\ddkon\Projects\uvicorn-win-test\venv\Scripts\uvicorn.exe\__main__.py", line 9, in <module>
File "c:\users\ddkon\projects\uvicorn-win-test\venv\lib\site-packages\click\core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "c:\users\ddkon\projects\uvicorn-win-test\venv\lib\site-packages\click\core.py", line 697, in main
rv = self.invoke(ctx)
File "c:\users\ddkon\projects\uvicorn-win-test\venv\lib\site-packages\click\core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "c:\users\ddkon\projects\uvicorn-win-test\venv\lib\site-packages\click\core.py", line 535, in invoke
return callback(*args, **kwargs)
File "c:\users\ddkon\projects\uvicorn-win-test\venv\lib\site-packages\uvicorn\main.py", line 50, in main
server.run()
File "c:\users\ddkon\projects\uvicorn-win-test\venv\lib\site-packages\uvicorn\main.py", line 142, in run
self.loop.run_forever()
File "c:\users\ddkon\anaconda3\Lib\asyncio\base_events.py", line 422, in run_forever
self._run_once()
File "c:\users\ddkon\anaconda3\Lib\asyncio\base_events.py", line 1396, in _run_once
event_list = self._selector.select(timeout)
File "c:\users\ddkon\anaconda3\Lib\selectors.py", line 323, in select
r, w, _ = self._select(self._readers, self._writers, [], timeout)
File "c:\users\ddkon\anaconda3\Lib\selectors.py", line 314, in _select
r, w, x = select.select(r, w, w, timeout)
File "c:\users\ddkon\projects\uvicorn-win-test\venv\lib\site-packages\uvicorn\main.py", line 145, in handle_exit
self.logger.warning("Received signal {}. Shutting down.".format(sig.name))
AttributeError: 'int' object has no attribute 'name'
Can it be terminated by process explorer or whatever?
Yes, it is visible in Task Manager and I was able to terminate it from there

Wonderful, thanks so much! 😎😎😎
So ‘pip install uvicorn’ raises an error then?
Will have to think about how to handle that gracefully. Presumably setup.py could detect if it’s being installed on windows and adapt the requirements. (Running with ‘—loop uvloop —http h11’ would make sense.)
The Ctrl-C exception looks easy enough to resolve.
And thanks again, that’s super-helpful!
One other installation issue: Currently setup.py uses the built-in open to read README. This would likely cause problems in the majority of Windows machines, where the default system encoding cannot decode the Unicorn emoji. This is not difficult to resolve for a Python 3-only project—simply add encoding='utf8' to open.
Getting past that (I cloned and manually deleted the emoji), you’ll hit the uvloop support problem mentioned previously:
> pip install .\uvicorn\
Processing c:\users\uranusjr\documents\playground\uvicorn-play\uvicorn
Collecting click (from uvicorn==0.2.12)
Using cached https://files.pythonhosted.org/packages/34/c1/8806f99713ddb993c5366c362b2f908f18269f8d792aff1abfd700775a77/click-6.7-py2.py3-none-any.whl
Collecting h11 (from uvicorn==0.2.12)
Using cached https://files.pythonhosted.org/packages/f9/f3/8e4cf5fa1a3d8bda942a0b1cf92f87815494216fd439f82eb99073141ba0/h11-0.8.1-py2.py3-none-any.whl
Collecting httptools (from uvicorn==0.2.12)
Using cached https://files.pythonhosted.org/packages/a3/75/40cdb732e8ef547d9f34ceb83c43ea7188c0ffb719ddc6a1ad160464292d/httptools-0.0.11.tar.gz
Collecting uvloop (from uvicorn==0.2.12)
Using cached https://files.pythonhosted.org/packages/cd/e5/1492d3a6ee52f261df764eece684513bb8abbe988d4bd3d94093f39e2bea/uvloop-0.11.0.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\uranusjr\AppData\Local\Temp\pip-install-mlbym38h\uvloop\setup.py", line 15, in <module>
raise RuntimeError('uvloop does not support Windows at the moment')
RuntimeError: uvloop does not support Windows at the moment
Some additional information.
Running with Python 3.7, httptools does not require me the whole Visual Studio to build. Minimal VS 2017 Build Tools setup (toolkit v14.1, CRT SDK, and Windows 10 SDK) is enough for me to get it working. I didn’t test, but imagine the same would apply for 3.6 (which also supports VSBT 14.1) and 3.5 (VSBT 14.0 should work here).
Windows detection is straightforward with modern PEP 508 support. A simple change to the uvloop requirement into
"uvloop; platform_system!='Windows'",
And it installs for me 😃
I am not sure what’s the actual requirement of uvloop, but maybe os_name=='posix' or sys_platform!='win32' could be better markers.
I'm glad I could help!
Yeah, it does raise an error, such as the one that @uranusjr posted.
I was thinking that it might be a good idea to make uvloop an optional dependency (Yuri Selivanov strongly advises to). What do you think?
I’d like the behaviour to be that it’s used by default, but falls back to asyncio gracefully. We’re very close to that now - just need a few tweaks to setup.py and modify the defaulting behaviour in main.py a little
Okay, I think we should be looking much better now! 👍
Version 0.2.13 released, with fixes from #130
Anyone able to give it a whirl? 😄
I would strongly recommend using PEP 508 environment markers to specify dependencies instead. This allows for the same effect (in relatively recent Setuptools and pip), prevents the packager from needing to maintain platform-specific artifacts (e.g. wheels), and has immensely better compatibility with the new trend of locking-aware dependency management tools like Pipenv and Poetry.
The following should be functionality-wise equivalent to the if-elif-else clause:
requirements = [
'click',
'h11',
'websockets>=6.0',
"httptools; platform_system != 'Windows' and 'CYGWIN' not in platform_system and platform_python_implementation != 'PyPy'",
"uvloop; platform_system != 'Windows' and 'CYGWIN' not in platform_system and platform_python_implementation != 'PyPy'",
]
Presumably things are problematic ATM, as we're importing httptools regardless of if it's installed or not.
@uranusjr Okay, I could be up for that. Any idea which versions of pip will support it, or if there's likely any other compatibility issues it could introduce?
The markers were introduced in Setuptools 36.2.0, released 2017-07-13. This version is officially bundled in ensurepip only after 3.6.5, but all major package managers have picked it up long before that.
Syntax support shouldn’t be a problem as long as the user updates setuptools (or pip, which implies a setuptools update) in a remotely regular basis. (And there is little reason not to, since setuptools maintains backward compatibility next to forever.) Practically I have yet to see anyone actually complain about this.
Practically I have yet to see anyone actually complain about this.
@uranusjr Okay - Are there any reasonably prominent examples of projects using it? (Just so I can make a call on ubiquity of support) Thanks for all this!
Treating this as a separate issue, at #135
I believe we now have functioning windows support from 0.2.14 onwards.
Confirmation from anyone would be ace! /cc @daniil-konovalenko @uranusjr
Running the example in README gives me the following error:
C:\Users\uranusjr\Documents\playground\uvicorn-play
(uvicorn-play) λ python -c "import uvicorn; print(uvicorn.__version__)"
0.2.14
C:\Users\uranusjr\Documents\playground\uvicorn-play
(uvicorn-play) λ uvicorn app:App
Traceback (most recent call last):
File "C:\Users\uranusjr\AppData\Local\Programs\Python\Python37\Lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "C:\Users\uranusjr\AppData\Local\Programs\Python\Python37\Lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Users\uranusjr\Documents\playground\uvicorn-play\.venv\Scripts\uvicorn.exe\__main__.py", line 9, in <module>
File "c:\users\uranusjr\documents\playground\uvicorn-play\.venv\lib\site-packages\click\core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "c:\users\uranusjr\documents\playground\uvicorn-play\.venv\lib\site-packages\click\core.py", line 697, in main
rv = self.invoke(ctx)
File "c:\users\uranusjr\documents\playground\uvicorn-play\.venv\lib\site-packages\click\core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "c:\users\uranusjr\documents\playground\uvicorn-play\.venv\lib\site-packages\click\core.py", line 535, in invoke
return callback(*args, **kwargs)
File "c:\users\uranusjr\documents\playground\uvicorn-play\.venv\lib\site-packages\uvicorn\main.py", line 55, in main
run(app, host, port, http, loop, log_level)
File "c:\users\uranusjr\documents\playground\uvicorn-play\.venv\lib\site-packages\uvicorn\main.py", line 64, in run
loop_setup = import_from_string(LOOP_SETUPS[loop])
File "c:\users\uranusjr\documents\playground\uvicorn-play\.venv\lib\site-packages\uvicorn\importer.py", line 20, in import_from_string
module = importlib.import_module(module_str)
File "c:\users\uranusjr\documents\playground\uvicorn-play\.venv\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 965, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'uvicorn.loops'
Didn’t look deep but it seems like a circular import problem?
I think we do now have windows support properly enabled again.
Confirmations from anyone would be much appreciated. 😄
(Also any thoughts on CI services that'd allow me to test against this?)
Can confirm uvicorn now works out of the package as of 0.2.22 🕺
Rad! ✨
Most helpful comment
Can confirm uvicorn now works out of the package as of 0.2.22 🕺