下载RoS2源码时的问题

引言

最近研究所新配了电脑, 需要在win10上部署ros2.
昨天开始照着官网的教程安装, 前期一切顺利, 直到Get The RoS2 Code这一步, 官网给的vcs import src < ros2.repos命令根本下载不了, 单独创建了文件夹, 没有任何实质的文件内被下载. 会报错TimeOut
面向百度编程也没有解决这个问题, 打算自己动手解决了.

思路

打开ros2.repos文件, 发现这就是个没后缀的yaml格式文件, 如下
在这里插入图片描述
显然, 给他复制一份(源文件我建议各位不要动), 命名ros2.yaml, 不难发现这里面包含了下载目录下载url两个信息. 举个例子, 如下的部分,

ament/googletest:
  type: git
  url: https://github.com/ament/googletest.git
  version: foxy

他表示要把https://github.com/ament/googletest.git下载到ament/googletest/目录下
幸运的是, 我发现挂了梯子后, git clone是可以直接下载上面的链接的. 但是官网给的vcs import src < ros2.repos就是下载不了, 网络就是这么玄学…

实战

全局变量

任何实战性的项目, 写日志都是个好习惯. 建议日志要包括时间(YYYY-MM-DD HH:MM"SS), 输出类型(INFO, WARNING, ERROR)和输出信息

root_dir = "C:/dev/ros2_foxy/"  					# 根目录
path_log = os.path.join(root_dir, 'log.txt')  		# 日志文件
repo_file = os.path.join(root_dir, "ros2.yaml")		# 读取的yaml文件
save_dir = os.path.join(root_dir, 'src/')			# 下载项保存的根目录
logger = open(path_log, 'w')						# 日志对象
fail_yaml = os.path.join(root_dir, "fail.yaml")		# 保存失败的repos

日志

任何有日志的项目, 第一个写的文件永远是cfg, 然后是日志logger.py, 这里日志比较简单, 就不另建文件了, 直接在同一个文件里定义如下函数

def log_string(out_str, dtype='INFO', to_log_file=True):
    """
    保存日志
    :param to_log_file:
    :param dtype:
    :param out_str:
    """
    global logger
    if not isinstance(out_str, str):
        out_str = str(out_str)

    if '\\r' == out_str:
        print()
        if to_log_file:
            logger.write('\n')
            logger.flush()
    else:
        local_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        out_str = '[{:^7s}] [{}] '.format(dtype, local_time) + out_str

        if 'INFO' == dtype:
            print(out_str)
        elif 'WARNING' == dtype:
            print("\033[0;34m{}\033[0m".format(out_str))
        else:
            print("\033[0;31m{}\033[0m".format(out_str))
        if to_log_file:

            logger.write(out_str + '\n')
            logger.flush()

\033[0;34m{}\033[0m这些字符没有太大意义, 只是为了能够在Pycharm中用不同颜色输出不同类型的信息.

读取ros2.yaml

这里用到了pyyaml模块, 读取上面复制好的ros2.yaml文件

fs = open(repo_file, encoding="UTF-8")
data = yaml.load(fs, Loader=yaml.FullLoader)['repositories']

这里我直接定位到了repositories这个key了, 此时的data仍然是一个dict, 如下
在这里插入图片描述
那么我们只需要按key来遍历data, 然后获取对应的url本地保存路径即可

遍历data并下载对应的url

这里需要用到os.system(cmd)函数, 它接受一个str参数cmd,功能是在系统终端内执行这个cmd, 并返回一个返回值, 如果成功, 返回值是0, 如果失败, 返回值五花八门, 反正不是0.

日志格式

动手前先想清楚, 日志需要以什么样的格式写出来. 我希望每一次下载, 都能够显示当前进度(当前第几个链接, 总共几个链接), 下载的链接, 执行的命令, 执行命令的返回值. 这样一来流程不会乱, 后续DEBUG也方便.
我保存的日志log.txt如下
在这里插入图片描述

处理问题

这里还要想一个问题, 我们现在知道了某一个链接git成功还是失败了, 成功了最好, 但是如果失败了呢? 一共99个链接, 虽然有日志可以查出来哪些链接失败了, 但是后续要怎么去git这些链接呢? 由于网络原因, 每次git同一个链接的结果可能是不一样的, 这次失败了, 下次可能就成功了.
如果不把这些失败的url保存下来, 那就还是只能手动去git, 我这么懒的人怎么会干这么累的事.
那必然是新建一个fail.yaml文件, 把所有失败的链接放里面, 跑完整个程序后, 重新读fail.yaml, 把里面的链接再下载一遍, 如此循环. 而且为了方便, 最好fail.yamlros2.yaml同样的结构, 如下是我保存的fail.yaml的内容, 可以看到和前面的ros2.yaml的结构是一样的
在这里插入图片描述

代码

fail_yaml = os.path.join(root_dir, "fail.yaml")
first_fail = True	
num = len(data.keys())
cnt = 0

# 每次运行都要把上次运行结果的fail.yaml清空
with open(fail_yaml, "w", encoding="utf-8") as f:
    pass

for key in data.keys():
    cnt += 1
    save_dir_tmp = os.path.join(save_dir, key+'/')
    if not os.path.exists(save_dir_tmp):
        os.makedirs(save_dir_tmp)
    url = data[key]['url']
    cmd = 'git clone {} {} --recursive'.format(url, save_dir_tmp)
    log_string('{}/{}, {}'.format(cnt, num, cmd))
    ret = os.system(cmd)
    if ret == 0:
        log_string('Success')
    else:
        log_string('Fail, ret={}, writing to fail.yaml'.format(ret), 'ERROR')
        # 第一次失败
        if first_fail:	
        	# yaml文件的第一行是repositories:, 这里第一次和后面几次有区别
            with open(fail_yaml, "a+", encoding="utf-8") as f:
                first_fail = False
                out = {'repositories': {key: data[key]}}
                yaml.dump(out, f)
        # 第n次失败
        else:
            with open(fail_yaml, "a+", encoding="utf-8") as f:
                yaml.dump({key: data[key]}, f)

    log_string('\\r')
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

对象被抛出

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值