0

i was using a python package (spotify_dl) to genereate some files. i was doing it manually through the command line: spotify_dl -l spotify_playlist_link -o download_directory

now i want to do it from inside another python script.

i looked at the package code and found the main function, but i can't figure how to run the main function with arguments of my choosing - in python.

for example what i want:

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)

for better clarity, here is the actual code of the spotify_dl main function:

#!/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', type=str, 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', type=str, action='store',
                        help='Specify youtube-dl format string.',
                        default='bestaudio/best')
    parser.add_argument('-k', '--keep_playlist_order', default=False,
                        action='store_true',
                        help='Whether to keep original playlist ordering or not.')
    parser.add_argument('-m', '--skip_mp3', action='store_true',
                        help='Don\'t convert downloaded songs to mp3')
    parser.add_argument('-s', '--scrape', action="store",
                        help="Use HTML Scraper for YouTube Search", default=True)
    parser.add_argument('-V', '--verbose', action='store_true',
                        help='Show more information on what''s happening.')
    parser.add_argument('-v', '--version', action='store_true',
                        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, key, 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, item_type, 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()

so far i could see mentions of sys.argv but also some comments spoke against using that. what i want is a clear method that i could run in a loop without complications.

2 Answers 2

2

spotify_dl is badly designed, I commonly use this:

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)

Then you can import this first script in another and call the main function:

from my_first_script import main

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

But you can workaround by overriding 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()
Sign up to request clarification or add additional context in comments.

Comments

0

You can use subprocess here. I did not try your example because I don't have those libraries installed, but here's a simple example.

First, a simple commandline script called testpy.py has the following:

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()

This takes one argument f and exports a text file (test.txt) with whatever argument was supplied.

This script can be run from a next script as (save this as new script file):

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

If you run this, you'll see that the file test.txt will be exported and calling the script testpy.py from this script was successful.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.