当前位置:网站首页>Why use pycharm to run the use case successfully but cannot exit?
Why use pycharm to run the use case successfully but cannot exit?
2022-07-03 21:26:00 【Quick and bold】
Related documents
Want to learn Python My friends can pay attention to Xiaobian's official account 【Python journal 】
There are many resources to whore for nothing , It will be updated from time to time Python Little knowledge of ha !!
Preface
Some time ago, due to a SDK It's upgraded , In the use of PyCharm+unittest When running a use case , Can run and output results , But has been unable to exit the use case . With the in-depth investigation , Found this SDK Thread in “ Make trouble ”.
Reproduce with simple code
Simplicity , Here's the code (Python 2) It contains simple thread logic and a use case , To reproduce the problems encountered :
# coding: utf-8
import threading
import time
import unittest
def tick():
while True:
print('tick')
time.sleep(3)
t = threading.Thread(target=tick)
t.start()
class TestString(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
This code starts a thread , every other 3 A second output tick. On the other hand , Define a use case , Determine the of the string upper() Method . If you delete thread logic , The use case can end normally ; conversely ,PyCharm Show the successful execution of the use case , But has been unable to exit the use case , As shown in the figure below :
Why not quit ?
A new thread must be opened before running the use case , perform tick() function , Because this function uses while The loop keeps outputting strings , It is not difficult to infer that the use case framework has been waiting for the thread to end when exiting , Thus, the use case cannot exit .
To test the idea , Check out PyCharm Run the entry code of the use case . Different operating systems 、PyCharm( Community Edition 、 pro ) It is different from the path of the use case entry file under the single test framework .Mac Upper PyCharm The Community Edition is for unittest The path of the case entry file of is
“/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pycharm/_jb_unittest_runner.py” ,
The contents of the document are as follows :
# coding=utf-8
import os
import sys
from unittest import main
from _jb_runner_tools import jb_start_tests, jb_doc_args, JB_DISABLE_BUFFERING, PROJECT_DIR
from teamcity import unittestpy
if __name__ == '__main__':
path, targets, additional_args = jb_start_tests()
args = ["python -m unittest"]
if path:
assert os.path.exists(path), "{0}: No such file or directory".format(path)
if sys.version_info > (3, 0) and os.path.isfile(path):
# In Py3 it is possible to run script directly which is much more stable than discovery machinery
# For example it supports hyphens in file names PY-23549
additional_args = [path] + additional_args
else:
discovery_args = ["discover", "-s"]
# Unittest in py2 does not support running script directly (and folders in py2 and py3),
# but it can use "discover" to find all tests in some folder (optionally filtering by script)
if os.path.isfile(path):
discovery_args += [os.path.dirname(path), "-p", os.path.basename(path)]
else:
discovery_args.append(path)
discovery_args += ["-t", PROJECT_DIR] # To force unit calculate path relative to this folder
additional_args = discovery_args + additional_args
elif targets:
additional_args += targets
args += additional_args
jb_doc_args("unittests", args)
# Working dir should be on path, that is how unittest work when launched from command line
sys.path.insert(0, PROJECT_DIR)
sys.exit(main(argv=args, module=None, testRunner=unittestpy.TeamcityTestRunner, buffer=not JB_DISABLE_BUFFERING))
The previous logic is mainly used to combine the parameters of running use cases , The key to the problem encountered in this article is the last line
main(argv=args, module=None,testRunner=unittestpy.TeamcityTestRunner, buffer=notJB_DISABLE_BUFFERING)
there main Namely unittest.TestProgram , The relevant core contents are as follows :
class TestProgram(object):
"""A command-line program that runs a set of tests; this is primarily for making test modules conveniently executable. """
USAGE = USAGE_FROM_MODULE
# defaults for testing
failfast = catchbreak = buffer = progName = None
def __init__(self, module='__main__', defaultTest=None, argv=None,
testRunner=None, testLoader=loader.defaultTestLoader,
exit=True, verbosity=1, failfast=None, catchbreak=None,
buffer=None):
...
self.exit = exit
...
self.parseArgs(argv)
self.runTests()
def runTests(self):
...
self.result = testRunner.run(self.test)
if self.exit:
sys.exit(not self.result.wasSuccessful())
PyCharm Of _jb_unittest_runner.py call main() ( namely TestProgram()) when , There was no introduction exit Parameters , So take the default True , In the specified runTests() Run the end of the use case , Determine the exit code according to the result of the use case (0 or 1), And then call sys.exit() Exit the use case execution process . If you break here, you will find that you have been stuck in this sentence .
sys.exit() The function of is to exit the current thread , If other threads do not end , Naturally, the process will not end . Obviously ,tick The thread of the function is not explicitly exited , As a result, the use case has been successfully run , But unable to quit .
How to solve ?
Now that you understand the reason , The solution is just around the corner .
Method 1 : Run the use case without executing thread logic
If the thread logic to perform periodic tasks is not required by the use case , Through the environment variable 、 Configuration files, etc , Thread logic is not executed when running the use case , So as to avoid that the use case cannot exit .
Method 2 : Explicitly exit the process instead of the thread
Use os._exit(n) Withdraw from the process . It should be noted that , This method does not call the cleanup logic 、 Refresh standard IO Cache, etc , It is usually used for fork() In the child process after . Because unit testing has no special requirements for the process , The test cases here generally do not cause side effects .
We can simply modify _jb_unittest_runner.py Final logic , Explicitly specify exit=False , That is not to let unittest call sys.exit() , It is called externally os._exit().
prog = main(argv=args, module=None, testRunner=unittestpy.TeamcityTestRunner, buffer=not JB_DISABLE_BUFFERING, exit=False)
os._exit(not prog.result.wasSuccessful())
Method 3 : Exit the thread gracefully
_jb_unittest_runner.py Send to the current process at the end of the use case run SIGKILL The signal , When the use case thread receives this signal , Execute cleanup logic ( If necessary ) Graceful exit , And then exit the process . This method will be discussed in detail in another article , This article knows this kind of thinking .
summary
If you pass PyCharm When executing the use case, the thread logic of running periodic tasks is triggered , Then it will lead to the completion of use case execution but cannot exit . The reason is sys.exit() Used to exit the current thread instead of the process , If a thread does not exit , This will cause the process to fail to exit . There are no more than three solutions , Do not execute thread logic 、 Exit the process or gracefully exit the thread .
边栏推荐
- Yyds dry inventory hcie security Day12: concept of supplementary package filtering and security policy
- The 12th Blue Bridge Cup
- Redis data migration (II)
- No matter how hot the metauniverse is, it cannot be separated from data
- Etcd 基于Raft的一致性保证
- Global and Chinese market of gallic acid 2022-2028: Research Report on technology, participants, trends, market size and share
- 使用dnSpy对无源码EXE或DLL进行反编译并且修改
- Yyds dry goods inventory TCP & UDP
- Solve the problem that openocd fails to burn STM32 and cannot connect through SWD
- Netfilter ARP log
猜你喜欢
Getting started with postman -- built-in dynamic parameters, custom parameters and assertions
Such as the visual appeal of the live broadcast of NBA Finals, can you still see it like this?
MySQL - index
Xai+ network security? Brandon University and others' latest "interpretable artificial intelligence in network security applications" overview, 33 page PDF describes its current situation, challenges,
Reinforcement learning - learning notes 1 | basic concepts
90 后,辞职创业,说要卷死云数据库
抓包整理外篇——————autoResponder、composer 、statistics [ 三]
(5) User login - services and processes - History Du touch date stat CP
Compilation Principle -- syntax analysis
如临现场的视觉感染力,NBA决赛直播还能这样看?
随机推荐
设计电商秒杀系统
What is the maximum number of concurrent TCP connections for a server? 65535?
Redis data migration (II)
Ask and answer: dispel your doubts about the virtual function mechanism
90 后,辞职创业,说要卷死云数据库
Analyse de REF nerf
抓包整理外篇——————autoResponder、composer 、statistics [ 三]
Selenium has three waiting methods (forced waiting, implicit waiting, and display waiting)
leetcode-540. A single element in an ordered array
The White House held an open source security summit, attended by many technology giants
Service discovery and load balancing mechanism -service
Advanced collaboration: coroutinecontext
Goodbye 2021, how do programmers go to the top of the disdain chain?
仿网易云音乐小程序
Kernel symbol table
[Yugong series] go teaching course 002 go language environment installation in July 2022
Solve the problem that openocd fails to burn STM32 and cannot connect through SWD
《ActBERT》百度&悉尼科技大学提出ActBERT,学习全局局部视频文本表示,在五个视频-文本任务中有效!...
Design e-commerce seckill system
treevalue——Master Nested Data Like Tensor