通过路径类型单击一旦导入的行为会有所不同
让我们想象我有一个简单的python脚本do_stuff.py
在给定文件夹中列出了子文件夹:
import click
@click.command(help="Do stuff.")
@click.argument('datasets', type=click.Path(exists=True, readable=True, writable=True), nargs=-1)
def main(datasets):
for dataset in datasets:
print(dataset)
if __name__ == "__main__":
main()
在我的情况下,它会在我运行python3 do_stuff.py./s3_data/时返回预期的文件夹列表。 lsc2/landsat_ot_c2_l2/*
:
./s3_data/lsc2/landsat_ot_c2_l2/LC08_L2SP_195027_20220121
./s3_data/lsc2/landsat_ot_c2_l2/LC08_L2SP_195027_20220206
./s3_data/lsc2/landsat_ot_c2_l2/LC08_L2SP_195027_20220222
./s3_data/lsc2/landsat_ot_c2_l2/LC08_L2SP_195027_20220310
当我尝试从另一个脚本做同样的事情master.py.py.py
时,导入do_stuff.py
:
from do_stuff import main as ds
ds('./s3_data/lsc2/landsat_ot_c2_l2/*')
当我运行时python3 master.py
它返回:
Usage: master.py [OPTIONS] [DATASETS]...
Try 'master.py --help' for help.
Error: Invalid value for '[DATASETS]...': Path '/' is not writable.
如果我将master.py.py
的最后一行修改为ds(['./ s3_data/lsc/lsc2/landsat_ot_ot_c2_l2/*'']))代码>,然后我得到:
Usage: master.py [OPTIONS] [DATASETS]...
Try 'master.py --help' for help.
Error: Invalid value for '[DATASETS]...': Path './s3_data/lsc2/landsat_ot_c2_l2/*' does not exist.
提前感谢您提供的任何帮助。
Let's imagine I have a simple Python script do_stuff.py
that lists subfolders in a given folder:
import click
@click.command(help="Do stuff.")
@click.argument('datasets', type=click.Path(exists=True, readable=True, writable=True), nargs=-1)
def main(datasets):
for dataset in datasets:
print(dataset)
if __name__ == "__main__":
main()
In my case it returns the expected list of folders when I run python3 do_stuff.py ./s3_data/lsc2/landsat_ot_c2_l2/*
:
./s3_data/lsc2/landsat_ot_c2_l2/LC08_L2SP_195027_20220121
./s3_data/lsc2/landsat_ot_c2_l2/LC08_L2SP_195027_20220206
./s3_data/lsc2/landsat_ot_c2_l2/LC08_L2SP_195027_20220222
./s3_data/lsc2/landsat_ot_c2_l2/LC08_L2SP_195027_20220310
When I try to do the same thing from another script master.py
, importing do_stuff.py
:
from do_stuff import main as ds
ds('./s3_data/lsc2/landsat_ot_c2_l2/*')
When I run python3 master.py
it returns:
Usage: master.py [OPTIONS] [DATASETS]...
Try 'master.py --help' for help.
Error: Invalid value for '[DATASETS]...': Path '/' is not writable.
If I modify the last line of master.py
into ds(['./s3_data/lsc2/landsat_ot_c2_l2/*'])
, then I get:
Usage: master.py [OPTIONS] [DATASETS]...
Try 'master.py --help' for help.
Error: Invalid value for '[DATASETS]...': Path './s3_data/lsc2/landsat_ot_c2_l2/*' does not exist.
Thanks in advance for any help you could provide.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为了使您充分理解看起来不同的行为,即您误以为“一旦导入路径类型的行为不同”,请建议您建议以下实验。在您的
do_stuff.py
中,检查什么参数单击
在命令行'./ s3_data/lsc2/landsat_ot_c2_l2/*'
是通过。这可以通过在main()
现在运行之前添加这对行来完成:
请注意它实际上是您拥有的四个文件的列表,而
*
无处不在在程序中可以看到。这是因为从外壳中,它自动在运行命令之前自动扩展通配符>,因此Python(因此单击
)只会看到完全合格的文件名,并且循环愉快地运行。一种简单的方法来模仿命令行(根据上一段中的链接线程,不必用
set glob
)来重复您从调用ds(Code> ds( './s3_data/lsc2/landsat_ot_c2_l2/*')
是在通配符的路径中传递,而通配符将无法解析为任何文件作为对程序的参数,在示例中,它模拟了调用
ds(['/tmp/a_dir_does_not_exist/*'])
根据问题中的失败示例。现在,如果您想从python内使用相同的地球语法,则可以使用
glob.glob
功能复制外壳中的自动通配符扩展,示例:In order for you to fully understand the behavior that looks different that you misattributed as "Click with Path type behavior differently once imported", may I recommend the following experiment. In your
do_stuff.py
, check what argumentsclick
actually received when from the command line'./s3_data/lsc2/landsat_ot_c2_l2/*'
was passed. This may be done by adding these couple lines beforemain()
Now run it:
Note how it's actually a list of the four files that you have, and the
*
is nowhere to be seen inside the program. This is because from the shell, it automatically expands the wildcard character before the command is actually run, so Python (thusclick
) will only see the fully qualified filenames and the loop runs happily.A easy way to emulate the failure from the command line (without having to muck about with
set glob
as per the linked thread in the previous paragraph) to repeat the failure you saw from callingds('./s3_data/lsc2/landsat_ot_c2_l2/*')
is to pass in a path with a wildcard that will not be resolved to any file, example:Since the shell cannot expand that wildcard argument, its unmodifed form is passed as an argument to the program, and in the example it emulates calling
ds(['/tmp/a_dir_does_not_exist/*'])
as per the failed example in the question.Now, if you want to use the same glob syntax from within Python, you may use the
glob.glob
function to replicate the automatic wildcard expansion in the shell, example: