-
Notifications
You must be signed in to change notification settings - Fork 214
support for a multiprocessing inside a subprocess? #139
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
FWIW I also dumped the environs for both the monitor (process b) and the worker (process c). (a) py.test
(b) monitor
(a) worker
This at least confirms that the environ variables are available to all of the processes. |
Does it still happen if you remove the coverage filter (eg: only use |
Yes I get the same result. |
@ionelmc Do you have any hints or initial thoughts? I'm happy to try and dig into this but I don't know much about this domain. I just know that pytest-cov is monkeypatching some calls to invoke coverage in each process and then combining the coverage results. My first guess is that it not running coverage on one of the processes or the results from that process are squashing some other results, causing them to appear to be missing. |
I discovered that if I drop |
Is anything like |
Ok, with some configuration changes I get this:
Is that expected result? |
I'm afraid you need to adopt a src layout to make this work well. I disabled all source filtering to get the result above ... The problem is that when you put |
See Pylons/hupper#7 |
Wow thanks @ionelmc. Let me respond inline.
No. There is just a
It is not. There are several lines at module scope that are not tracked. For example, in both processes b and c the
What if I use |
I'll investigate further, probably an answer next week. Feel free to find different configuration (like using |
I went into this at least a little bit deeper but I'm still pretty confused. It doesn't appear as if coverage is watching the subprocess at all, except that there is some minimal amount of coverage reported for a couple of the modules. I found https://coverage.readthedocs.io/en/coverage-4.2/subprocess.html#configuring-python-for-sub-process-coverage for handling subprocess coverage, but it seems to me that pytest-cov is handling this in its own way via a .pth file, except it isn't calling |
@ionelmc Any chance to look at this? Is there an example somewhere of a working subprocess setup I can look at? |
Well the test have lots of stuff with subprocesses. But they are quite simplistic, compared to your project. I still want to figure this out ... lets see when I get to it 😔 |
Here's my latest coverage report:
This is after tweaking the coveragerc a bit more. Many of these lines I would expect to be covered, such as everything in
|
I think I figured out what the problem is: pytest-cov uses "multiprocessing finalizers" and that don't seem to work with Anyway, meanwhile I'm looking for a solution, any idea how to make mp reliably run some code in a process even if it's |
Ok, one thing that works is something like
I'm starting to lean towards looking a solution in multiprocessing, rather than workaround in pytest-cov ... |
IMO we should shift the burden to the user in such a special case. If the user is terminating a coverage process it should be his responsibility to clean up everything. To assist we could help with a shortcut for According to the docs |
Thanks for the ideas.
I'm not sure how to test this. The Are you sure this is an issue with multiprocessing? I think at least part of the issue is that coverage does not appear to be running in the subprocess b (not c which is run via multiprocessing). |
I thought the problem was process „c”. And about the API and „cov” object, we can fix it so it's usable from user's code. |
Some examples of why I think the issue is mostly b:
To be clear b is also a subprocess that's terminated via the test harness and so could suffer from improper cleanup as well but I don't know how to check that. |
My test suite calls subprocesses that run multiprocessing using pytest-cov, and it also fails to pick up anything that happens inside my worker processes, while it does collect work done in the initial subprocess. It so happens my multiprocessing is handled by a library (ruffus) that allows one to switch to multithreading and take cares of the details somewhat transparently. I held my nose, switched on multithreading, and pytest-cov picked up everything. (And hey, 74%... not a bad start.) My tests terminate processes normally by closing a process pool. The results in the multiprocessing case are the same whether or not I also tried |
Alright, give the master branch a try. Suggested use: # in the subprocess
from pytest_cov.embed import cleanup_on_sigterm
cleanup_on_sigterm() Full example: https://github.com/pytest-dev/pytest-cov/blob/master/tests/test_pytest_cov.py#L783-L784 |
So I've finally revisited this after rewriting hupper to use subprocess instead of multiprocessing. I'm happy to say that That being said, import signal
import pytest_cov.embed
def cleanup(*_):
pytest_cov.embed.cleanup()
sys.exit(1)
signal.signal(signal.SIGTERM, cleanup) |
Feel free to use I could make |
I can confirm this fix has improved my coverage reports. It's used here: Pylons/hupper@88da99e One final note... it might be smart to register this by default when I wish I knew a good way to do this on windows as well but http://stackoverflow.com/a/35792192/704327 doesn't paint a pretty picture. |
On Fri, May 12, 2017 at 5:33 AM, Michael Merickel ***@***.***> wrote:
One final note... it might be smart to register this by default when
pytest_cov.embed.init is invoked. 1) This would not require saving the
active_cov global, and 2) it would be less of a gotcha for folks doing
coverage in subprocesses.
Can you expand on this? You mean automatically registering the signal
handler?
|
Yeah that's what I was suggesting. pytest-cov jumps through hoops to register a pth and get in on the coverage game early - I think it makes sense it would try to cleanup as well. |
What if there's already a registered sig handler? Should we wrap the old sigterm handler? |
That'd probably make sense. I wish there was a way to guarantee cleanup on windows as well but I don't really know of one. At the end of the day the use-case of getting coverage on a subprocess that is designed to not exit normally is obviously not an ideal approach. |
I think this should be enough: 509f77f#diff-6926f77e5b0c63b4908e3ed385e64a20 Comment or make PR if you want something else. |
I'm working on https://github.com/Pylons/hupper. It's a forking process monitor. I've tried a lot of permutations of pytest-cov and haven't found any success.
The process hierarchy is this:
Here is an example output, but first some observations:
--cov
flags enabled. This is because of the "No data was collected" messages in the worker process (this is process c in the above diagram). There should definitely be data collected if things were working correctly.tests/myapp/__main__.py
however lines 1-10 are missing, which are at module scope. What?.coverage.alai.27676.269523
file left over. Presumably this file is not getting combined with the rest of the output, but that's just a guess.I'd really appreciate any insights here as I have no experience getting coverage reports when in a multiprocessing/subprocess environment but as far as I can tell my setup follows the guidelines (each process has pytest-cov installed and environment variables are propagated).
The text was updated successfully, but these errors were encountered: