Closed GeeCastro closed 7 months ago
@Chichilele
============================= test session starts ==============================
collecting ... collected 2 items
issue.py::test_get_threading PASSED [ 50%]
issue.py::test_get_multiprocessing PASSED [100%]
can you find another reproducible ? I run on python 3.11
python 3.8
I don’t have access to a laptop this week but found something interesting. See this GitHub action run with macOS fails https://github.com/Chichilele/reponses-thread-issue/actions/runs/6865230936/job/18668751152
but the previous one with Ubuntu passed! https://github.com/Chichilele/reponses-thread-issue/actions/runs/6865141529
@Chichilele so you assume that is OS specific ? could it be python bug then ?
The test above indicates it’s OS specific indeed. I wouldn’t know where it comes from though. Maybe python, maybe another package called by responses to mock the http calls
@Chichilele I just forked your repo and confirm that changing OS from macos to ubuntu resolves the issue
can you simplify your example further down and remove poetry? I see that this installs other sets of dependencies for poetry and not sure if poetry isolates environment good enough
Good point I’ve tried here without poetry. Pip install requests, responses and pytest then running pytest
https://github.com/Chichilele/reponses-thread-issue/actions/runs/6867570438/job/18676216103
I did a debug on MacOS VM
we do patch the adapter.send()
from responses
. However, when we reach to the execution point, requests
asks to send via adapter and then adapter send is the original one.
same happens when we use context manager.
I think it is some bug on Mock
from python, or python itself. Our function patch doesn't propagate across processes on MacOS
@markstory have you even encountered smth like this ?
@beliaev-maksim This may be because of how processed are started slightly different on MacOS, vs Linux - see this answer on SO: https://stackoverflow.com/a/70440892/13245310
And some info on how to change the start_method
for a specific ProcessPoolExecutor
:
https://superfastpython.com/processpoolexecutor-multiprocessing-context/
@bblommers thanks a lot for the links. That indeed explains, if the process is executed in a separate interpreter, then there is no way we can catch it.
from the docs follows that this issue could be solved from the user side, but it feels like only on MacOS, meaning that we will not be able to solve it on Windows
that also might be different in the sequence of execution. In the provided example we first do the mock, then create a pool. What if we create a mock inside of the pool, then each copy of the interpreter gets its own responses. It will mess up things like call_counts (since they will not be global) but should intercept all the requests
anyway, nothing that could be done from responses
side.
@Chichilele if you would like to contribute documentation on how to solve this issue from user side, that would be great
have you even encountered smth like this ?
I have not, but having mocks cross process boundaries (with either fork or spawning) is not something I would expect a python library to take care of either.
Describe the bug
Reponses works with
ThreadPoolExecutor
but doesn't withProcessPoolExecutor
. I'm guessing it may be because the underlying process doesn't get the responses setup when spawned? But just in case I thought I'd ask if there was a solution for my tests.Additional context
Here’s a minimal setup to reproduce the issue
https://github.com/Chichilele/reponses-thread-issue
Version of
responses
0.23.3
Steps to Reproduce
runs with pytest or main and throws an error:
Details
``` python3.10 test_concurrent.py Running threading... Running multiprocessing... concurrent.futures.process._RemoteTraceback: """ Traceback (most recent call last): File "/Users/gauthiercastro/code/ml-sc-training-pipeline/.venv/lib/python3.10/site-packages/urllib3/connection.py", line 174, in _new_conn conn = connection.create_connection( File "/Users/gauthiercastro/code/ml-sc-training-pipeline/.venv/lib/python3.10/site-packages/urllib3/util/connection.py", line 72, in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): File "/Users/gauthiercastro/.pyenv/versions/3.10.12/lib/python3.10/socket.py", line 955, in getaddrinfo for res in _socket.getaddrinfo(host, port, family, type, proto, flags): socket.gaierror: [Errno 8] nodename nor servname provided, or not known During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/Users/gauthiercastro/code/ml-sc-training-pipeline/.venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 714, in urlopen httplib_response = self._make_request( File "/Users/gauthiercastro/code/ml-sc-training-pipeline/.venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 415, in _make_request conn.request(method, url, **httplib_request_kw) File "/Users/gauthiercastro/code/ml-sc-training-pipeline/.venv/lib/python3.10/site-packages/urllib3/connection.py", line 244, in request super(HTTPConnection, self).request(method, url, body=body, headers=headers) File "/Users/gauthiercastro/.pyenv/versions/3.10.12/lib/python3.10/http/client.py", line 1283, in request self._send_request(method, url, body, headers, encode_chunked) File "/Users/gauthiercastro/.pyenv/versions/3.10.12/lib/python3.10/http/client.py", line 1329, in _send_request self.endheaders(body, encode_chunked=encode_chunked) File "/Users/gauthiercastro/.pyenv/versions/3.10.12/lib/python3.10/http/client.py", line 1278, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/Users/gauthiercastro/.pyenv/versions/3.10.12/lib/python3.10/http/client.py", line 1038, in _send_output self.send(msg) File "/Users/gauthiercastro/.pyenv/versions/3.10.12/lib/python3.10/http/client.py", line 976, in send self.connect() File "/Users/gauthiercastro/code/ml-sc-training-pipeline/.venv/lib/python3.10/site-packages/urllib3/connection.py", line 205, in connect conn = self._new_conn() File "/Users/gauthiercastro/code/ml-sc-training-pipeline/.venv/lib/python3.10/site-packages/urllib3/connection.py", line 186, in _new_conn raise NewConnectionError( urllib3.exceptions.NewConnectionError:Expected Result
Tests pass, mocking urls for both
ThreadPoolExecutor
andProcessPoolExecutor
Actual Result
Mocking urls for both
ThreadPoolExecutor
but reaches actual website withProcessPoolExecutor