join() 参数必须是 str、bytes 或 os.PathLike 对象,而不是 'NoneType'

join() argument must be str, bytes, or os.PathLike object, not 'NoneType'

我正在使用 python 创建一个 CLI 工具并点击。我有一个名为 ext 的命令,它有两个选项 --type--path,然后是另一个命令 ext。该函数根据给定类型中指定的扩展名组织指定路径中的文件。这是我得到的命令和错误:

Categorize ext --type image --path C:\Users\ACERq\Pictures\Screenshots ext
join() argument must be str, bytes, or os.PathLike object, not 'NoneType'

我有另一个类似的命令,它只接受一个路径选项,该函数在同一路径下可以正常工作

import click
from src.services.ext_functions import *

class Context:
    def __init__(self, type, path):
        self.type = type
        self.path = path

@click.group()
@click.option("-t", "--type", type=str, help = "Type of extension", required=False, default="media")
@click.option("-p", "--path", type=str, help = "Path to organize", required=False, default=os.getcwd())
@click.pass_context
def main(ctx, type, path):
    """Organize files based on extension"""
    ctx.obj = Context(type, path)
    pass

@main.command()
@click.pass_context
def ext(ctx):
    """Organize files based on specified extension types"""
    extension = ctx.obj.type
    folder_to_track = ctx.obj.path
    click.echo(extension_category(extension, folder_to_track))

@main.command()
@click.pass_context
def all(ctx):
    """Organize all files based on extension types"""
    folder_to_track = ctx.obj.path
    click.echo(all_extensions_category(folder_to_track))

完整追溯

Traceback (most recent call last):
  File "D:\Python-projects\Categorize-CLI\.venv\Scripts\Categorize-script.py", line 33, in <module>
    sys.exit(load_entry_point('Categorize-CLI', 'console_scripts', 'Categorize')())
  File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\decorators.py", line 26, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "d:\python-projects\categorize-cli\src\commands\ext.py", line 23, in ext
    click.echo(extension_category(extension, folder_to_track))
  File "d:\python-projects\categorize-cli\src\services\ext_functions.py", line 82, in extension_category
    folder_path = os.path.join(folder_to_track, folder_name)
  File "C:\Users\ACERq\AppData\Local\Programs\Python\Python310\lib\ntpath.py", line 117, in join
    genericpath._check_arg_types('join', path, *paths)
  File "C:\Users\ACERq\AppData\Local\Programs\Python\Python310\lib\genericpath.py", line 152, in _check_arg_types
    raise TypeError(f'{funcname}() argument must be str, bytes, or '
TypeError: join() argument must be str, bytes, or os.PathLike object, not 'NoneType'

extension_category()

def extension_category(extension, folder_to_track):
    start_time = time.monotonic()
    movedFiles = False
    count = 0
    if check_files(folder_to_track):
        for file in os.listdir(folder_to_track):
            if not os.path.isdir(os.path.join(folder_to_track, file)):
                try:
                    file_mappings = collections.defaultdict()
                    for filename in os.listdir(folder_to_track):
                        for value in extension:
                            if not os.path.isdir(os.path.join(folder_to_track, filename)) and any(
                                    filename.endswith(value) for filename in os.listdir(folder_to_track)) == True:
                                file_mappings.setdefault(get_key(extension), []).append(filename)

                    for folder_name, folder_items in file_mappings.items():
                        folder_path = os.path.join(folder_to_track, folder_name)
                        folder_exists = os.path.exists(folder_path)
                        if not folder_exists:
                            os.mkdir(folder_path)

                            for filename in os.listdir(folder_to_track):
                                for value in extension:
                                    if not os.path.isdir(os.path.join(folder_to_track, filename)) and filename.endswith(
                                            value):
                                        count = count + 1
                                        source = os.path.join(folder_to_track, filename)
                                        destination = os.path.join(folder_path, filename)
                                        moveIncrementing(source,destination)  # move all files containing sub_file_name in their filenames
                                        movedFiles = True

                        if folder_exists:
                            for filename in os.listdir(folder_to_track):
                                for value in extension:
                                    if not os.path.isdir(os.path.join(folder_to_track, filename)) and filename.endswith(
                                            value):
                                        count = count + 1
                                        source = os.path.join(folder_to_track, filename)
                                        destination = os.path.join(folder_path, filename)
                                        moveIncrementing(source,
                                                         destination)  # move all files containing sub_file_name in their filenames
                                        movedFiles = True

                    end_time = time.monotonic()

                    displayProgressbar(count)

                    if movedFiles:
                        if count == 1:
                            return f"Successfully moved {count} file{os.linesep}Time taken: {timedelta(seconds=end_time - start_time)}"
                        else:
                            return f"Successfully moved {count} files{os.linesep}Time taken: {timedelta(seconds=end_time - start_time)}"
                    else:
                        return "Files with that extension do not exist in {}".format(folder_to_track)

                except Exception as e:
                    print(e)
                    return f'{folder_to_track}: is either empty or not organizable'

    else:
        return f'{folder_to_track}: is either empty or not organizable'

如果我这样调用函数:extension_category(image, r"C:\Users\ACERq\Pictures\Screenshots") 它有效

更新 我设法使它工作,但后来我遇到了一个新问题

当我只是检查输入的值是否等于扩展名时它可以工作,但是当我添加更多修改时它不起作用

我终于解决了这个问题,我认为问题是由于参数 folder_to_track 但实际上是第二个参数 extension 导致了问题。该函数将参数作为 extensions-dict 的值而不是键。所以扩展名不是 image,而是 [".png", ".jpg"] etc

import click
from src.services.ext_functions import *

class Context:
    def __init__(self, type, path):
        self.type = type
        self.path = path

@click.command()
@click.option("-t", "--type", type=str, help = "Type of extension", required=True)
@click.option("-p", "--path", type=str, help = "Path to organize", required=False, default=os.getcwd())
@click.pass_context
def main(ctx, type, path):
    """Organize files based on extension"""
    ctx.obj = Context(type, path)
    extension = ctx.obj.type
    folder_to_track = ctx.obj.path
    
    categories = [key for key, value in extensions.items()]
    if extension in categories and os.path.exists(folder_to_track):
        click.echo(extension_category(extensions[extension], folder_to_track))
    elif not extension in categories:
        click.echo("{} is not one of the types of extensions".format(extension))
    elif not os.path.exists(folder_to_track):
        click.echo("{}: does not exist".format(folder_to_track))