当前位置:网站首页>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 .
边栏推荐
- Advanced technology management - how to examine candidates in the interview and increase the entry probability
- Rhcsa third day notes
- MySQL - database backup
- Global and Chinese market of AC induction motors 2022-2028: Research Report on technology, participants, trends, market size and share
- Ask and answer: dispel your doubts about the virtual function mechanism
- Getting started with postman -- environment variables and global variables
- Capture de paquets et tri du contenu externe - - autoresponder, composer, statistiques [3]
- @Scenario of transactional annotation invalidation
- 鹏城杯 WEB_WP
- Selenium has three waiting methods (forced waiting, implicit waiting, and display waiting)
猜你喜欢

Design e-commerce seckill system

Yiwen teaches you how to choose your own NFT trading market

Monkey/ auto traverse test, integrate screen recording requirements

leetcode-540. A single element in an ordered array

使用dnSpy对无源码EXE或DLL进行反编译并且修改

Such as the visual appeal of the live broadcast of NBA Finals, can you still see it like this?

Summary of common operation and maintenance commands

APEC industry +: father of the king of the ox mill, industrial Internet "king of the ox mill anti-wear faction" Valentine's Day greetings | Asia Pacific Economic media | ChinaBrand

强化學習-學習筆記1 | 基礎概念
![Capture de paquets et tri du contenu externe - - autoresponder, composer, statistiques [3]](/img/bf/ac3ba04c48e80b2d4f9c13894a4984.png)
Capture de paquets et tri du contenu externe - - autoresponder, composer, statistiques [3]
随机推荐
C程序设计的初步认识
JS notes (III)
Is it OK for fresh students to change careers to do software testing? The senior answered with his own experience
XAI+网络安全?布兰登大学等最新《可解释人工智能在网络安全应用》综述,33页pdf阐述其现状、挑战、开放问题和未来方向
Borui data and Sina Finance released the 2021 credit card industry development report
Redis concludes that the second pipeline publishes / subscribes to bloom filter redis as a database and caches RDB AOF redis configuration files
常用sql集合
技术管理进阶——如何在面试中考察候选人并增大入职概率
"Designer universe" APEC safety and health +: environmental protection Panda "xiaobaobao" Happy Valentine's Day 2022 | ChinaBrand | Asia Pacific Economic media
How to install sentinel console
抓包整理外篇——————autoResponder、composer 、statistics [ 三]
Link aggregation based on team mechanism
2022-02-15 Daily: 2022 AAAI fellow release
University of Electronic Science and technology | playback of clustering experience effectively used in reinforcement learning
Qualcomm platform WiFi update disconnect end open event
Global and Chinese market of wall mounted kiosks 2022-2028: Research Report on technology, participants, trends, market size and share
Brief analysis of ref nerf
MySQL - SQL injection problem
Xai+ network security? Brandon University and others' latest "interpretable artificial intelligence in network security applications" overview, 33 page PDF describes its current situation, challenges,
Kubernetes 通信异常网络故障 解决思路