全局命名空间中的 argparse 参数将覆盖其他文件的参数

argparse argument in global namespace will override other file's arguments

这是我在自动脚本开发过程中注意到的一个行为。 现在我有两个文件名 main.pytest.py,
main.py代码:

#!/usr/bin/env python3
import argparse
import os
import sys
import time
from pathlib import Path
import pytest
import configparser as cpaser

test_config = {}

def config_test_env():
    global test_config
    case_path = Path(base_dir, 'testcase')
    now = time.strftime("%Y-%m-%d_%H-%M-%S")
    test_reports_address = Path(base_dir, 'report')
    test_log_address = Path(base_dir, 'log')
    if not test_reports_address.exists():
        os.mkdir(test_reports_address)
    if not test_log_address.exists():
        os.mkdir(test_log_address)
    filepath = Path(test_reports_address, now + "_report.html")
    test_config['filepath'] = str(filepath)
    parser = argparse.ArgumentParser(description='main.py - excute testcases')
    parser.add_argument('-H', '-Host', dest='host', help='host url', default='http://192.168.1.169')
    parser.add_argument('-t', dest='testcase_path', help='testcase path', type=str, default=case_path)
    parser.add_argument('-r', dest='test_report_path', help='testreport path', default=filepath)
    parser.add_argument('-m', help='run specific mark type testcase',
                        choices=['smoke_test', 'ui_test', 'api_test', 'demonstration'])
    parser.add_argument('--driver', help='specific webdriver to perform UI test', default='chrome')
    parser.add_argument('-s', help='print testcase execute result on screen', action='store_true')
    parser.add_argument('-c', help='enable code coverage check', action='store_true')
    parser.add_argument('-cr', '-check_response_time', help='check API reponse time', dest='ct', action='store_true',
                        default=False)
    parser.add_argument('-dc', '-delete_case', dest='delete_case_flag',
                        help='whether delete case after testcase finish',
                        action='store_true', default=False)
    parser.add_argument('-mt', '-max_response_time', dest='mt', help='api max response time set', default=30, type=int)
    parser.add_argument('-sr', '-send_report', dest='send_report', help='whether send report after test excute',
                        action='store_true', default=False)
    args = parser.parse_args()
    host = str(args.host)
    test_config['host'] = host
    ct_flag = args.ct
    csv_file_path = str(Path(base_dir, host.split('//')[1] + '_api_response_time.csv'))
    test_config['csv_file_path'] = csv_file_path
    test_config['ct_flag'] = ct_flag
    mt = args.mt
    test_config['mt'] = mt
    if ct_flag:
        create_csv_file(csv_file_path)
    dc_flag = args.delete_case_flag
    test_config['dc_flag'] = dc_flag
    test_config['send_report'] = args.send_report
    pytest_args = [
        '-v',
        str(args.testcase_path),
        '--html=' + str(args.test_report_path),
        '--self-contained-html',
        '--driver', str(args.driver)
    ]
    test_config['pytest_args'] = pytest_args


config_test_env()

if __name__ == '__main__':
    # pytest main
    pass

test.py代码:

from main import test_config

if __name__ == '__main__':
    # pytest main
    parser = argparse.ArgumentParser(description='store case using thread')
    parser.add_argument('-t', '-total', dest='total_case', help='total_case number', type=int, default=100)
    parser.add_argument('-r', dest='per_round', help='case number per round, thread number', type=int, default=100)
    args = parser.parse_args()
    pass

我想 main.py 设置一些全局变量,所以我将方法 config_test_env 放在全局命名空间中并更新全局 test_confg 以便可以被其他文件导入。
但是当我执行 python3 test.py -h 时,输出是:

usage: test2.py [-h] [-H HOST] [-t TESTCASE_PATH] [-r TEST_REPORT_PATH] [-m {smoke_test,ui_test,api_test,demonstration}] [--driver DRIVER] [-s] [-c] [-cr] [-dc] [-mt MT] [-sr]

main.py - excute testcases

optional arguments:
  -h, --help            show this help message and exit
  -H HOST, -Host HOST   host url
  -t TESTCASE_PATH      testcase path
  -r TEST_REPORT_PATH   testreport path
  -m {smoke_test,ui_test,api_test,demonstration}
                        run specific mark type testcase
  --driver DRIVER       specific webdriver to perform UI test
  -s                    print testcase execute result on screen
  -c                    enable code coverage check
  -cr, -check_response_time
                        check API reponse time
  -dc, -delete_case     whether delete case after testcase finish
  -mt MT, -max_response_time MT
                        api max response time set
  -sr, -send_report     whether send report after test excute

显然 test.py 参数似乎被 main.py 覆盖,所以我想知道可以从 main.py 导入全局变量但也不会覆盖参数

当您执行 from main import test_config 时,整个 main 模块正在执行。

因为对 config_test_env() 的调用不受 if __name__ == '__main__': 的保护,它作为导入的一部分被调用。

在此调用中,您定义一个 parser,然后调用 args = parser.parse_args()。因为你 运行 和 -h,对 parse_args 的调用打印了(main 的)帮助消息并退出了程序。


至于解决这个问题,很难说,因为我不完全明白你在做什么。要么将 config_test_env() 放在 if __name__ == '__main__': 下,或者至少只在文件是主文件时才执行 parser 创建。