使用来自另一个脚本的参数启动 python 脚本,以编程方式设置 argparse 值

如何解决使用来自另一个脚本的参数启动 python 脚本,以编程方式设置 argparse 值

我正在使用 python 包 (spotify_dl) 来生成一些文件。我是通过命令行手动完成的: spotify_dl -l spotify_playlist_link -o download_directory

现在我想从另一个 Python 脚本中执行此操作。

我查看了包代码并找到了 main 函数,但我不知道如何使用我选择的参数运行 main 函数 - 在 python 中。

例如我想要的:

from spotify_dl import spotify_dl as sp_dl

if __name__=='__main__':
    destination_dir = r'D:\some\folder\path'
    playlists_url = ['url1','url2','url3',....]

    for url in playlists_url:
        sp_dl.spotify_dl(l=url,o=destination_dir)

为了更清晰,这里是 spotify_dl 主函数的实际代码

#!/usr/bin/env python
import argparse
import json
import os
import sys
from logging import DEBUG
from pathlib import Path,PurePath

import spotipy
from spotipy.oauth2 import SpotifyClientCredentials

from spotify_dl.constants import VERSION
from spotify_dl.models import db,Song
from spotify_dl.scaffold import log,check_for_tokens
from spotify_dl.spotify import fetch_tracks,parse_spotify_url,validate_spotify_url,get_item_name
from spotify_dl.youtube import download_songs,default_filename,playlist_num_filename


def spotify_dl():
    """Main entry point of the script."""
    parser = argparse.ArgumentParser(prog='spotify_dl')
    parser.add_argument('-l','--url',action="store",help="Spotify Playlist link URL",type=str,required=True)
    parser.add_argument('-o','--output',action='store',help='Specify download directory.',required=True)
    parser.add_argument('-d','--download',action='store_true',help='Download using youtube-dl',default=True)
    parser.add_argument('-f','--format_str',help='Specify youtube-dl format string.',default='bestaudio/best')
    parser.add_argument('-k','--keep_playlist_order',default=False,help='Whether to keep original playlist ordering or not.')
    parser.add_argument('-m','--skip_mp3',help='Don\'t convert downloaded songs to mp3')
    parser.add_argument('-s','--scrape',help="Use HTML Scraper for YouTube Search",default=True)
    parser.add_argument('-V','--verbose',help='Show more information on what''s happening.')
    parser.add_argument('-v','--version',help='Shows current version of the program')
    args = parser.parse_args()

    if args.version:
        print("spotify_dl v{}".format(VERSION))
        exit(0)

    db.connect()
    db.create_tables([Song])
    if os.path.isfile(os.path.expanduser('~/.spotify_dl_settings')):
        with open(os.path.expanduser('~/.spotify_dl_settings')) as file:
            config = json.loads(file.read())

        for key,value in config.items():
            if value and (value.lower() == 'true' or value.lower() == 't'):
                setattr(args,key,True)
            else:
                setattr(args,value)

    if args.verbose:
        log.setLevel(DEBUG)

    log.info('Starting spotify_dl')
    log.debug('Setting debug mode on spotify_dl')

    if not check_for_tokens():
        exit(1)

    sp = spotipy.Spotify(auth_manager=SpotifyClientCredentials())
    log.debug('Arguments: {}'.format(args))

    if args.url:
        valid_item = validate_spotify_url(args.url)

    if not valid_item:
        sys.exit(1)

    if args.output:
        item_type,item_id = parse_spotify_url(args.url)
        directory_name = get_item_name(sp,item_type,item_id)
        save_path = Path(PurePath.joinpath(Path(args.output),Path(directory_name)))
        save_path.mkdir(parents=True,exist_ok=True)
        log.info("Saving songs to: {}".format(directory_name))

    songs = fetch_tracks(sp,args.url)
    if args.download is True:
        file_name_f = default_filename
        if args.keep_playlist_order:
            file_name_f = playlist_num_filename

        download_songs(songs,save_path,args.format_str,args.skip_mp3,args.keep_playlist_order,file_name_f)


if __name__ == '__main__':
    spotify_dl()

到目前为止,我可以看到提到 sys.argv,但也有一些评论反对使用它。 我想要的是一个清晰的方法,我可以在循环中运行而不会出现并发症。

解决方法

spotify_dl 设计得很糟糕,我经常使用这个:

def parse_args(argv=None):
    parser = argparse.ArgumentParser()
    ...
    return parser.parse_args(argv)

def main(args):
    # run your code

if __name__ == "__main__":
    args = parse_args()
    main(args)

然后您可以在另一个脚本中导入第一个脚本并调用 main 函数:

from my_first_script import main

def a_function():
    args = namedtuple("args",("arg1",...))("value1")
    main(args)

但您可以通过覆盖 sys.argv 来解决:

if __name__=='__main__':
    destination_dir = r'D:\some\folder\path'
    playlists_url = ['url1','url2','url3',....]

    for url in playlists_url:
        sys.argv = [sys.executable,"-o",destination_dir,"-l",url]
        sp_dl.spotify_dl()
,

您可以在此处使用 subprocess。 我没有尝试你的例子,因为我没有安装这些库,但这是一个简单的例子。

首先,一个名为 testpy.py 的简单命令行脚本具有以下内容:

import sys
import argparse
def check_arg(args=None):
    parser = argparse.ArgumentParser(prog='Test',description='Test',epilog='Test')
    parser.add_argument('-f','--first',help='First argument',required='True')
    results = parser.parse_args(args)
    return (results.first)



def main():
    with open('test.txt','a') as file:
        file.write('Success,{}\n'.format(f))


if __name__ == '__main__':
    f = check_arg(sys.argv[1:])
    main()

这需要一个参数 f 并使用提供的任何参数导出一个文本文件 (test.txt)。

此脚本可以从下一个脚本运行为(将其另存为新脚本文件):

from subprocess import run,PIPE
args = ['python3','testpy.py','-f','First input argument text']
res = run(args,stdout=PIPE,stderr=PIPE)

如果您运行此程序,您将看到文件 test.txt 将被导出,并且从此脚本调用脚本 testpy.py 成功。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?