Skip to content

pytest.main(...) hangs but works if run with subprocess.check_output #4434

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

Closed
tjprescott opened this issue Nov 21, 2018 · 26 comments
Closed
Labels
status: critical grave problem or usability issue that affects lots of users type: bug problem that needs to be addressed

Comments

@tjprescott
Copy link

In my code, I call pytest.main(arguments) to run Pytest.

        arguments = ['-p', 'no:warnings', '--no-print-logs', '--junit-xml', log_path]
        arguments.extend(test_paths)
        if parallel:
            arguments += ['-n', 'auto']
        if pytest_args:
            arguments += pytest_args
        logger.info('Running: pytest {}'.format(' '.join(arguments)))
        return pytest.main(arguments)

This code hangs when run on OSX (10.14.1) but works fine on Windows.

If I change the last line to instead essentially call pytest through subprocess.check_output it executes fine. It also works if I simply copy-paste the command to my terminal. This behavior is observed whether I specify -n=auto or not, which is why I'm posting this here instead of in pytest-xdist. Is there something I'm doing wrong here?

Pip List

pytest (4.0.0)
pytest-forked (0.2)
pytest-xdist (1.24.1)

OS Info

Python (Darwin) 2.7.10 (default, Aug 17 2018, 17:41:52) 
[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.0.42)]
@tjprescott
Copy link
Author

If I run the command with --debug, here is the snippet of the trace where it hangs:

[worker-gw2] sending logfinish {'nodeid': 'azure/cli/command_modules/redis/tests/latest/test_redis_scenario.py::RedisCacheTests::test_redis_cache', 'location': ('../../../env/lib/python2.7/site-packages/azure_devtools/scenario_tests/preparers.py', 26, 'RedisCacheTests.test_redis_cache')}
[worker-gw2] sending runtest_protocol_complete {'duration': 1.1219720840454102, 'item_index': 0}
[worker-gw2] sending workerfinished {'workeroutput': {'exitstatus': 1}}

Essentially, it has reported that the worker (and the only test) is finished, but processing stops at that point until I kill the process.

@blueyed
Copy link
Contributor

blueyed commented Nov 21, 2018

Does using -s as an argument to pytest make a difference?

@blueyed blueyed added the type: bug problem that needs to be addressed label Nov 21, 2018
@nicoddemus
Copy link
Member

--debug is useful, thanks. Can you please also post --debug without -n=auto? Thanks

@tjprescott
Copy link
Author

The run hangs when I run with Python 2.7 (default on OSX). If I run on Python 3 it seems to work without modification. -s doesn't help with Python 2.

@tjprescott
Copy link
Author

If run in series on Python 2 with debug, I get this trace:

================================================================================ test session starts ================================================================================
platform darwin -- Python 2.7.10, pytest-4.0.0, py-1.7.0, pluggy-0.8.0 -- /Users/travisprescott/github/azure-cli/env/bin/python
using: pytest-4.0.0 pylib-1.7.0
setuptools registered plugins:
  pytest-xdist-1.24.1 at /Users/travisprescott/github/azure-cli/env/lib/python2.7/site-packages/xdist/looponfail.py
  pytest-xdist-1.24.1 at /Users/travisprescott/github/azure-cli/env/lib/python2.7/site-packages/xdist/plugin.py
  pytest-forked-0.2 at /Users/travisprescott/github/azure-cli/env/lib/python2.7/site-packages/pytest_forked/__init__.pyc
rootdir: /Users/travisprescott/github/azure-cli/src/command_modules/azure-cli-redis, inifile:
plugins: xdist-1.24.1, forked-0.2
collected 1 item                                                                                                                                                                    

src/command_modules/azure-cli-redis/azure/cli/command_modules/redis/tests/latest/test_redis_scenario.py 

It then hangs.

@nicoddemus
Copy link
Member

hmmm didn't you see writing pytestdebug information to c:\pytest\pytestdebug.log at the start of the output?

@tjprescott
Copy link
Author

Ah, yes, that was the line just prior to "test session starts"

@nicoddemus
Copy link
Member

nicoddemus commented Nov 21, 2018

Does that file exist in your machine? I was under the impression it would get written even if the process never finished.

@tjprescott
Copy link
Author

It does. I can send you the file for each case, one where is hangs on Python 2, and one where it succeeds in Python 3. Should I send it to the email in your profile?

@cdeil
Copy link

cdeil commented Nov 22, 2018

We also have CI builds where pytest hangs. They are on Python 2.7 and with pytest 4.0, see gammapy/gammapy#1940 (comment) .

I tried setting PYTEST_DEBUG=1, but then there's too much output in the log and the CI services abort the build - not sure how to figure out why pytest hangs. I'll try reproducing the issue locally.

@cdeil
Copy link

cdeil commented Nov 22, 2018

I can reproduce the issue locally on MacOS with this conda env.yml like this:

git clone https://github.com/gammapy/gammapy.git
cd gammapy
time conda env create -f env.yml
conda activate gammapy-gh-1940
time python setup.py test -V

pytest hangs forever at very high CPU load. This shows continued printout of such lines:

$ PYTEST_DEBUG=1 time python setup.py test -V 
<snip>
early skip of rewriting module: h5py [assertion]
early skip of rewriting module: multiprocessing.random [assertion]
<snip>

These commands should let you reproduce the issue locally. If needed, I could try to create a more minimal conda environment or docker image that shows the issue.

It looks like pytest 4.0 has a serious issue under Python 2.7 for some environments, no?

@nicoddemus
Copy link
Member

It does. I can send you the file for each case, one where is hangs on Python 2, and one where it succeeds in Python 3. Should I send it to the email in your profile?

Please post it here in an issue, thanks (you can drag and drop the files to the issue text box directly)

@nicoddemus
Copy link
Member

@cdeil thanks for posting a reproducible case, unfortunately I'm on Windows and I can't recreate your environment:

ResolvePackageNotFound:
  - healpy
  - sherpa

healpy and sherpa probably are not available on Windows.

The early skip of rewriting module messages are expected, unless they appear for the same module more than once (which should not really happen).

Can you pass options to pytest with your setup.py test invocation? Could you please try -s, and --assert=plain, to see how that behaves? Also, now that you have reproduced the problem locally, can you attach the produced log here? Thanks, appreciate it. 👍

It looks like pytest 4.0 has a serious issue under Python 2.7 for some environments, no?

Not sure if this is an issue with Python 2.7 specifically, nothing that came out in 2.7 comes to mind (we only changed some pytest warnings into errors, really).

Also, what happens if you use 3.10.1 instead of 4.0.0?

@nicoddemus nicoddemus added the status: critical grave problem or usability issue that affects lots of users label Nov 22, 2018
@cdeil
Copy link

cdeil commented Nov 22, 2018

@nicoddemus - Can you try this simpler env?

conda create -n pytest-4434 python=2.7 cython numpy scipy astropy regions click pyyaml pytest
conda activate pytest-4434

and then the same:

git clone https://github.com/gammapy/gammapy.git
cd gammapy
time python setup.py test -V

or

pytest -v gammapy

will hang.
Now I see it hangs here:

gammapy/__init__.py::test

Does this mean it collected the gammapy.test function in the top-level package as a test to execute? That shouldn't happen (and didn't with other pytest versions). cc @astrofrog

https://github.com/gammapy/gammapy/blob/9981b0baefed1e16cfa8b19e8cbb7d2a9f4f3f63/gammapy/_astropy_init.py#L36

@nicoddemus - I'll try to follow your other suggestions locally. Maybe I should try to make a Docker image that has the issue, then you can execute it and have a look more easily?

@cdeil
Copy link

cdeil commented Nov 22, 2018

What's happening is that pytest calls pytest again:
https://gist.github.com/cdeil/b1ab5916546103d64f34c788100c63f7
So this is another symptom of something wrong in the Astropy package-template how the pytest function is implemented in astropy_init.py.
Probably the same underlying issue as for the issue reported here: #4390

So it might not be connected to the issue reported by @tjprescott here originally, although it also sounds like you might be calling pytest recursively?

I still don't know what to do here. Should _astropy_init.py be patched?
Or should an entry be made in setup.cfg to prevent that __init__.py::test is collected as a test and recursively called?
Given that this issue only appeared with never versions of pytest and on some platform, maybe something can be improved in pytest?

@nicoddemus
Copy link
Member

@cdeil can you try with pytest 3.10? I ask because you have the environment on your hand so it should be simple to try it.

pytest has been collected packages (and tests within them) for some time now (3.8? I think) so I want to know if the problem is related with that.

@cdeil
Copy link

cdeil commented Nov 22, 2018

With pytest 3.10 I get this, i.e. no tests are collected at all:
https://gist.github.com/cdeil/d5029fab585fe68df77fb91685570b78

With pytest 3.7, I get this AttributeError
https://gist.github.com/cdeil/4c950865e6e2da8f30d0ece8858b98d5

pytest 3.6 is the last version where it works.
I see that 8 days ago @pllim and @bsipocz did astropy/ci-helpers#340 i.e remove the pin to pytest < 3.6 in our CI.
That explains why we're seeing the issues now.

Still not sure what to do here. Maybe we should simply exclude gammapy.test which is the runner from the test collection? What's the best way to do this?

https://github.com/gammapy/gammapy/blob/9981b0baefed1e16cfa8b19e8cbb7d2a9f4f3f63/gammapy/_astropy_init.py#L36

@nicoddemus
Copy link
Member

@cdeil thanks a lot for testing things out. You are right, the problem seems to be with the fact that the test runner will start executing things when imported directly. Somewhere we need to add an if __name__ == "__main__" guard to avoid this.

Can you jump on Gitter real quick? I suspect we might be able to solve this quickly on chat.

@nicoddemus
Copy link
Member

@cdeil and I figured the problem after some quick poking around: gammpy.__init__ provides a test() function which starts a test run using astropy's runner. The test function is generated by _astropy_init.py.

pytest since 3.8 collects __init__, and was looking at this module and executing test() as a function.

Setting __test__ = False on the function itself prevents pytest considering it a test function. 👍

@astrofrog
Copy link

@nicoddemus - thank you for diagnosing this!

@cdeil
Copy link

cdeil commented Nov 22, 2018

@nicoddemus - You are awesome!

@tjprescott - Are you also accidentally running pytest from pytest like we are? Or is it a different one? If the second, I am really sorry for derailing your issue report; I should have opened a separate issue.

@astrofrog - I will send PRs with the one-line change for the Astropy and package-template repos.

@tjprescott
Copy link
Author

@cdeil I'm not sure what you mean by "running pytest from pytest". I was simply trying to call pytest.main(…) which works fine in Python 3 but hangs in Python 2. I have a workaround where I use subprocess.call to do the same thing and it doesn't hang, so I'm doing that.

@tjprescott
Copy link
Author

Here are the debug logs.

failed_pytestdebug.log
success_pytestdebug.log

@nicoddemus
Copy link
Member

Hi @tjprescott,

Unfortunately the logs don't tell much, all hooks have been called in what seems to be the correct order. 😕

Given that you have found a workaround and we have ran out of ways to debug this, I propose we close this issue.

@nicoddemus
Copy link
Member

Thanks. I'm sorry we couldn't get to the bottom of your problem.

@tjprescott
Copy link
Author

No worries. It's entirely possible I was just "doing it wrong". Thanks for looking into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: critical grave problem or usability issue that affects lots of users type: bug problem that needs to be addressed
Projects
None yet
Development

No branches or pull requests

5 participants