Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there any way that can transfer path string to pathlib.Path object? #260

Closed
shichao-wang opened this issue May 19, 2020 · 5 comments
Closed

Comments

@shichao-wang
Copy link

I have some function that use pathlib.Path as argument, like following script

from pathlib import Path
import fire


def test_fire(path: Path):
    print(type(path))
    print(path)


if __name__ == "__main__":
    fire.Fire(test_fire)

I simply test it with this.

python test_fire.py "/some_path_string"

<class 'str'>
/some_path_string

I expect to get a pathlib.Path object rather than str. Is there any way that I can do this?
Thanks a lot.

@MichaelCG8
Copy link
Contributor

Hi,

You've added a type hint for your test_fire function, specifying that path should be an instance of Path. Python does not enforce type hints though, see the typing documentation and PEP 484 where it was specified.

When you call test_fire() you pass it a string, and it stays a string. It is not converted to a Path object.

You can make your function accept either a str or a Path, and then used it like a Path like this:

from pathlib import Path
from typing import Union

def test_fire(path: Union[str, Path]):
    path = Path(path)  # This converts a str to a Path.  If already a Path, nothing changes.
    print(type(path))
    print(path)

This will give you the output:

<class 'pathlib.WindowsPath'>
WindowsPath('some_path_string')  # On unix you would get an equivalent of WindowsPath.

FYI, pull request #251 adds the types to the helptext. This is not merged yet, but when it is you would see the pathlib type when you access the helptext like:

 python test_fire.py --help

@shichao-wang
Copy link
Author

Hi, Michael.
That would be a solution, but with a little messy.
I will felt confused seeing this signature with following line path = Path(path) if I did not know about fire.
Maybe it will be a good idea to resolve arguments' type before passing it to function.

Thank you, anyway.

@MichaelCG8
Copy link
Contributor

Hi, this isn't a thing that is particular to Fire, it is the case for all of Python.

In any Python project (whether they use Fire or not) you can pass any type to a function. This is called Duck Typing and the reason that Python uses it is that it makes functions more flexible.

Python doesn't care what type you give it, so long as it can use that type in the way you want. For example, think about this function. The type hint says a Path, but type hints are ignored when your program runs. path is passed to open() which works fine with either a str or path.

def make_file(path: Path):
    with open(path) as out_file:
        out_file.write("Hello, World.")

If you call make_file() with a str or a Path it will work in either case.

Fire isn't my project, so this would not be my decision, but I think automatically converting types would be confusing since that would be different from the rest of Python.

I know this can be confusing so feel free to ask any questions about how duck typing works.

@luxuncang
Copy link

我有一些使用pathlib的函数。路径作为参数,如下面的脚本

from pathlib import Path
import fire


def test_fire(path: Path):
    print(type(path))
    print(path)


if __name__ == "__main__":
    fire.Fire(test_fire)

我只是用这个测试它。

python test_fire.py "/some_path_string"

<class 'str'>
/some_path_string

我希望得到一个对象而不是.有什么方法可以做到这一点吗? 多谢。pathlib.Path``str

可以看看 typefire

@zqqqqz2000
Copy link

Try afire! Which is a fork of python-fire supporing type convert according to the type hint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants