-
Notifications
You must be signed in to change notification settings - Fork 507
nbdev_prepare
fails with concurrent.futures.process.BrokenProcessPool
exception
#673
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
Comments
This might be due to #648 (the second comment)
Can you try that and see if it works? |
I'm getting this too but while developing on the nbdev repo itself, which I assume doesn't have the
running each of |
If you set
which could be related to the issue here. The final question is why the same issue isn't triggered when running |
In a Python file e.g.
and run it via Open an IPython repl and run the exact same code and it fails the same way as |
Issue comes from this line: https://github.com/fastai/nbdev/blob/master/nbdev/test.py#L38 |
In
(and comment out a few other things that fail at import time e.g. Then |
Just commenting out |
In So I think if we only do |
Unfortunately with wildcard imports it's very difficult to tell what imports are used (unless I haven't figured out the right tools?). I think it's just these two functions: https://github.com/fastai/nbdev/blob/master/nbdev/cli.py#L167 and https://github.com/fastai/nbdev/blob/master/nbdev/cli.py#L167 |
Heh - no it's not you, it's me. ;) I'm planning to write a tool that optionally converts them to explicit imports. Might be nice to also have something which simply reports what's being used. |
Thanks for looking into this! @warner-benjamin The settings.ini file for my project has
I'm not sure if/how that should be modified. Based on the following snippet, I also think fastcore_net_exports = ['url_default_headers', 'ExceptionsHTTP', 'urlquote', 'urlwrap', 'HTTP4xxClientError', 'HTTP5xxServerError', 'urlopen',
'urlread', 'urljson', 'urlcheck', 'urlclean', 'urlretrieve', 'urldest', 'urlsave', 'urlvalid', 'urlrequest',
'urlsend', 'do_request', 'start_server', 'start_client', 'HTTP400BadRequestError',
'HTTP401UnauthorizedError', 'HTTP402PaymentRequiredError', 'HTTP403ForbiddenError', 'HTTP404NotFoundError',
'HTTP405MethodNotAllowedError', 'HTTP406NotAcceptableError', 'HTTP407ProxyAuthRequiredError',
'HTTP408RequestTimeoutError', 'HTTP409ConflictError', 'HTTP410GoneError', 'HTTP411LengthRequiredError',
'HTTP412PreconditionFailedError', 'HTTP413PayloadTooLargeError', 'HTTP414URITooLongError',
'HTTP415UnsupportedMediaTypeError', 'HTTP416RangeNotSatisfiableError', 'HTTP417ExpectationFailedError',
'HTTP418AmAteapotError', 'HTTP421MisdirectedRequestError', 'HTTP422UnprocessableEntityError',
'HTTP423LockedError', 'HTTP424FailedDependencyError', 'HTTP425TooEarlyError', 'HTTP426UpgradeRequiredError',
'HTTP428PreconditionRequiredError', 'HTTP429TooManyRequestsError', 'HTTP431HeaderFieldsTooLargeError',
'HTTP451LegalReasonsError']
with open("nbdev/cli.py") as f:
s_code = f.read()
for x in fastcore_net_exports:
if x in s_code:
print(x) I agree it would be nice if an IDE could help with this import tracking. After commenting out the Code I copied in: # Copied from fastcore.net
import urllib
from urllib.parse import urlencode,urlparse,urlunparse
from urllib.request import Request
import json
_opener = urllib.request.build_opener()
def urlquote(url):
"Update url's path with `urllib.parse.quote`"
subdelims = "!$&'()*+,;="
gendelims = ":?#[]@"
safe = subdelims+gendelims+"%/"
p = list(urlparse(url))
p[2] = urllib.parse.quote(p[2], safe=safe)
for i in range(3,6): p[i] = urllib.parse.quote(p[i], safe=safe)
return urlunparse(p)
def urlwrap(url, data=None, headers=None):
"Wrap `url` in a urllib `Request` with `urlquote`"
return url if isinstance(url,Request) else Request(urlquote(url), data=data, headers=headers or {})
def urlopen(url, data=None, headers=None, timeout=None, **kwargs):
"Like `urllib.request.urlopen`, but first `urlwrap` the `url`, and encode `data`"
if kwargs and not data: data=kwargs
if data is not None:
if not isinstance(data, (str,bytes)): data = urlencode(data)
if not isinstance(data, bytes): data = data.encode('ascii')
return _opener.open(urlwrap(url, data=data, headers=headers), timeout=timeout)
class HTTP4xxClientError(HTTPError):
"Base class for client exceptions (code 4xx) from `url*` functions"
pass
ExceptionsHTTP = {}
_httperrors = (
(400,'Bad Request'),(401,'Unauthorized'),(402,'Payment Required'),(403,'Forbidden'),(404,'Not Found'),
(405,'Method Not Allowed'),(406,'Not Acceptable'),(407,'Proxy Auth Required'),(408,'Request Timeout'),
(409,'Conflict'),(410,'Gone'),(411,'Length Required'),(412,'Precondition Failed'),(413,'Payload Too Large'),
(414,'URI Too Long'),(415,'Unsupported Media Type'),(416,'Range Not Satisfiable'),(417,'Expectation Failed'),
(418,'Am A teapot'),(421,'Misdirected Request'),(422,'Unprocessable Entity'),(423,'Locked'),(424,'Failed Dependency'),
(425,'Too Early'),(426,'Upgrade Required'),(428,'Precondition Required'),(429,'Too Many Requests'),
(431,'Header Fields Too Large'),(451,'Legal Reasons')
)
for code,msg in _httperrors:
nm = f'HTTP{code}{msg.replace(" ","")}Error'
cls = get_class(nm, 'url', 'hdrs', 'fp', sup=HTTP4xxClientError, msg=msg, code=code)
globals()[nm] = ExceptionsHTTP[code] = cls
def urlread(url, data=None, headers=None, decode=True, return_json=False, return_headers=False, timeout=None, **kwargs):
"Retrieve `url`, using `data` dict or `kwargs` to `POST` if present"
try:
with urlopen(url, data=data, headers=headers, timeout=timeout, **kwargs) as u: res,hdrs = u.read(),u.headers
except HTTPError as e:
if 400 <= e.code < 500: raise ExceptionsHTTP[e.code](e.url, e.hdrs, e.fp) from None
else: raise
if decode: res = res.decode()
if return_json: res = loads(res)
return (res,dict(hdrs)) if return_headers else res
def urljson(url, data=None, timeout=None):
"Retrieve `url` and decode json"
res = urlread(url, data=data, timeout=timeout)
return json.loads(res) if res else {}
# End of fastcore.net stuff |
This is fixed now. Thanks for all your helpful investigations |
(Having said that - the fact that importing fastcore.parallel multiple times can break things is not good! I will look into it. If anyone can figure out what's going on, do let me know...) |
@jph00 I commented out the fastcore.net import and just added in import urllib
_opener = urllib.request.build_opener() and the same error occurs. Not sure why though. Thanks for fixing it! And nbdev, fastai, etc. |
Confirming that the commit Jeremy pushed fixes it for me |
It fixed it for me as well. |
It really was the urllib stuff... |
I haven't figured it out but I think there are a few key pieces of evidence:
here's what I think is happening:
Now something about this reasoning isn't quite correct as I tested out moving the above code inside the An alternative is to use "spawn" instead of "fork" but I don't know the history behind the decision to specify fork. UpdateAfter writing all the above I came across this post. And guess what, this works:
I have no idea if setting this environment variable before running the process is a bad idea, or a terrible idea however. |
@dleen would you mind sharing the latest minimal reproducible example of this issue? I've been battling with this (and related multiprocessing) issues on mac as well, and can share a few thoughts:
|
After the recent fix you can add back:
to (Strangely adding Btw my Python version is 3.9.13... |
Minimal reproducible example: from execnb.shell import CaptureShell
from fastcore.parallel import parallel
from urllib.request import _get_proxies
_get_proxies() # <-- breaks
def f(x): CaptureShell()
if __name__ == '__main__': parallel(f, [1]) |
Wow what a strange situation... can confirm that this fails for me too. Wonder if it has to do with the threading here? https://github.com/python/cpython/blob/main/Modules/_scproxy.c#L178 |
@dleen yes that seems like the issue These articles are super helpful:
Current fix in mind is to change |
I've made this fix now. Thanks gang! |
nbdev_prepare
is giving me aconcurrent.futures.process.BrokenProcessPool
on a new project.Environment
Steps to produce this error
Error message
The text was updated successfully, but these errors were encountered: