# 使用Modelarts训练yolov5出现报错TypeError: modelarts\_pre\_process\(\) missing 1 required positional argument:’args’

**1. 系统环境**

硬件环境\(Ascend/GPU/CPU\): Ascend910

软件环境: MindSpore 版本: 2.1.0

执行模式： 不限

Python 版本: 3.7

操作系统平台: linux

**2. 报错信息**

2.1 问题描述

在Modelarts里面的训练作业里面训练yolov5，出现报错。使用的代码：[https://gitee.com/mindspore/models/blob/master/official/cv/YOLOv5](https://gitee.com/mindspore/models/blob/master/official/cv/YOLOv5)

2.2 报错信息

在default\_config.yaml文件里面enable\_modelarts参数是False的时候出现如下报错：

```
FileNotFoundError:[Error 2] No such file or directory:’/cache/data/annotations/instances_train2017.json’
```

但是在enable\_modelarts为False的时候，在notbook环境下，是可以正常跑通训练的。把enable\_modelarts改为True的时候，在训练界面，就可以找到路径了，但是会报下面的错误。

```
TypeError: modelarts_pre_process() missing 1 required positional argument:’args’
```

并且把enable\_modelarts改为True的时候，在notbook环境下，也会报和上述相同的错误。

**3. 根因分析**

1.default\_config.yaml文件里面enable\_modelarts参数是False 报

```
FileNotFoundError:[Error 2] No such file or directory:’/cache/data/annotations/instances_train2017.json’
```

这个报错是因为代码走到了训练流程里面，因为环境里面没数据集导致。这个只要在对应位置放置数据集就行。

2.enable\_modelarts改为True 报

```
TypeError: modelarts_pre_process() missing 1 required positional argument:’args’
```

其实这里还没走到训练流程，这个是前置流程。

train.py 128行代码定义了moxing\_wrapper这个装饰器

```
@moxing_wrapper(pre_process=modelarts_pre_process, post_process=modelarts_post_process, pre_args=[config])
def run_train():
```

这个装饰器定义在 official/cv/YOLOv5/model\_utils/moxing\_adapter.py

```
def moxing_wrapper(pre_process=None, post_process=None, **kwargs):
    """
    Moxing wrapper to download dataset and upload outputs.
    """
    def wrapper(run_func):
        @functools.wraps(run_func)
        def wrapped_func(*args, **kwargs):
            # Download data from data_url
            if config.enable_modelarts:
                if config.data_url:
                    sync_data(config.data_url, config.data_path)
                    print("Dataset downloaded: ", os.listdir(config.data_path))
                if config.checkpoint_url:
                    sync_data(config.checkpoint_url, config.load_path)
                    print("Preload downloaded: ", os.listdir(config.load_path))
                if config.train_url:
                    sync_data(config.train_url, config.output_path)
                    print("Workspace downloaded: ", os.listdir(config.output_path))

                mindspore.set_context(save_graphs_path=os.path.join(config.output_path, str(get_rank_id())))
                config.device_num = get_device_num()
                config.device_id = get_device_id()
                if not os.path.exists(config.output_path):
                    os.makedirs(config.output_path)

                if pre_process:
                    if "pre_args" in kwargs.keys():
                        pre_process(*kwargs["pre_args"])
                    else:
                        pre_process()

            # Run the main function
            run_func(*args, **kwargs)

            # Upload data to train_url
            if config.enable_modelarts:
                if post_process:
                    if "post_args" in kwargs.keys():
                        post_process(*kwargs["post_args"])
                    else:
                        post_process()

                if config.train_url:
                    print("Start to copy output directory")
                    sync_data(config.output_path, config.train_url)
        return wrapped_func
    return wrapper
```

出问题的是modelarts\_pre\_process 这个函数，该函数有一个参数，但是调用的时候并没有参数传递过去。

也就是下面的代码走到了else分支。

```
if "pre_args" in kwargs.keys():
    pre_process(*kwargs["pre_args"])
else:
    pre_process()
```

为什么传递给装饰器的kwargs一开始是有值的，但是变成了空呢？

问题出在了official/cv/YOLOv5/model\_utils/moxing\_adapter.py

```
第136行
def moxing_wrapper(pre_process=None, post_process=None, **kwargs):
第142行
def wrapped_func(*args, **kwargs):
以及162行
if "pre_args" in kwargs.keys():


def moxing_wrapper(pre_process=None, post_process=None, **kwargs):
    """
    Moxing wrapper to download dataset and upload outputs.
    """
    def wrapper(run_func):
        @functools.wraps(run_func)
        def wrapped_func(*args, **kwargs):
...
            if pre_process:
                if "pre_args" in kwargs.keys():
                    pre_process(*kwargs["pre_args"])
                else:
                    pre_process()
```

外层的moxing\_wrapper和内层的wrapped\_func都使用了kwargs这个参数名。

而if "pre\_args" in kwargs.keys\(\):这个判断明显的判断外层的装饰器输入的参数，而不是内层的被装饰的函数。

**4. 解决方案**

修改文件 official/cv/YOLOv5/model\_utils/moxing\_adapter.py

修改重名的 kwargs ，另外一个可以用其他的名称代替。这里内部函数修改为wrap\_kwargs。

```
def moxing_wrapper(pre_process=None, post_process=None, **kwargs):
    """
    Moxing wrapper to download dataset and upload outputs.
    """
    def wrapper(run_func):
        @functools.wraps(run_func)
        def wrapped_func(*args, **wrap_kwargs):
            # Download data from data_url
            if config.enable_modelarts:
                if config.data_url:
                    sync_data(config.data_url, config.data_path)
                    print("Dataset downloaded: ", os.listdir(config.data_path))
                if config.checkpoint_url:
                    sync_data(config.checkpoint_url, config.load_path)
                    print("Preload downloaded: ", os.listdir(config.load_path))
                if config.train_url:
                    sync_data(config.train_url, config.output_path)
                    print("Workspace downloaded: ", os.listdir(config.output_path))

                mindspore.set_context(save_graphs_path=os.path.join(config.output_path, str(get_rank_id())))
                config.device_num = get_device_num()
                config.device_id = get_device_id()
                if not os.path.exists(config.output_path):
                    os.makedirs(config.output_path)

                if pre_process:
                    if "pre_args" in kwargs.keys():
                        pre_process(*kwargs["pre_args"])
                    else:
                        pre_process()

            # Run the main function
            run_func(*args, **wrap_kwargs)

            # Upload data to train_url
            if config.enable_modelarts:
                if post_process:
                    if "post_args" in kwargs.keys():
                        post_process(*kwargs["post_args"])
                    else:
                        post_process()

                if config.train_url:
                    print("Start to copy output directory")
                    sync_data(config.output_path, config.train_url)
        return wrapped_func
    return wrapper
```

