某处事情停止了。目的是在未提供参数的情况下显示当前磁盘使用情况,在作为参数提供的情况下显示目录的使用情况,并在给出--all参数的情况下显示所有子目录的磁盘使用情况。这是我到目前为止所得到的。由于某种原因,现在在为目录提供"-d"
时失败。
#!/usr/bin/env python
import os
import sys
import subprocess
import getopt
from humanize import naturalsize
def get_size(start_path = '.'):
total_size = 0
for dirpath, dirnames, filenames in os.walk(start_path):
for f in filenames:
fp = os.path.join(dirpath, f)
total_size += os.path.getsize(fp)
return total_size
def get_immediate_subdirectories(a_dir):
return [name for name in os.listdir(a_dir)
if os.path.isdir(os.path.join(a_dir, name))]
def version():
print ("Version: 1.0")
def usage():
print ("Usage: disk_usage.py [-a|--all][-n|--ncdu][-v|--version][directory name]")
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "adhnv", ["all","directory","help","ncdu","version",])
except getopt.GetoptError as err:
# print help information and exit:
print(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)
for o, a in opts:
if o in ("-a", "--all"):
for subdir in get_immediate_subdirectories('.'):
print ("%s\t\t %s" % (naturalsize(get_size(subdir)),subdir))
sys.exit()
elif o in ("-d", "--directory"):
print (naturalsize(get_size(start_path=sys.argv[1:])))
elif o in ("-v", "--version"):
print (version())
sys.exit()
elif o in ("-h", "--help"):
usage()
sys.exit()
elif o in ("-n", "--ncdu"):
os.system('ncdu')
sys.exit()
else:
print (usage())
main()
答案 0 :(得分:1)
我发现您使用getopt
存在一些问题。一种(听起来像是您已经自己弄清楚了)是通过将get_size()
传递给start_path=sys.argv[1:]
到{{1} }中的所有命令参数。
第二个问题是您没有正确定义传递给start_path
的第二个和第三个参数。引用PyMOTW3:
第二个参数是单个字符选项的选项定义字符串。 如果其中一个选项需要一个参数,则其字母后跟一个冒号。
(重点是我的)
这意味着,为了与list
选项一起接受值,您需要使用getopt()
而不是已经获得的-d
。
类似地,对于长样式选项列表中的"ad:hnv"
选项:
第三个参数(如果使用)应为长型选项名称的序列。长样式选项可以超过单个字符,例如--noarg或--witharg。序列中的选项名称不应包含“-”前缀。 如果任何长选项需要参数,则其名称后缀应为“ =”。
要在此提供支持,还需要您通过"adhnv"
。
很遗憾,--directory
不支持使用可选的option参数。原因很可能是因为它使解析变得模棱两可:例如,如果["all", "directory=", "help", "ncdu", "version"]
带有可选参数,而getopt
完全是另一个选项,则不清楚如何解释-a
。
如果您可以忍受这一限制,则以下内容将合并以解决上述问题:
-b
答案 1 :(得分:0)
我想我明白了。第42行包含sys.argv [1:],它返回了一个列表。提供-d选项后,实际上应该是sys.argv [2]来引用目录。
答案 2 :(得分:0)
这里有两个问题。
第一个问题是您使用的getopt
错误:
opts, args = getopt.getopt(sys.argv[1:], "adhnv", ["all","directory","help","ncdu","version",])
这将返回选项opts
的列表,以及args
的列表,其中已滤除选项。但是您将继续使用sys.argv
而不是args
:
print (naturalsize(get_size(start_path=sys.argv[1:])))
在像myprogram -d spam
这样的调用中,sys.argv[1:]
将是['-d', 'spam']
。但是您不希望-d
。这就是您首先致电getopts
的全部原因。因此,请在此处使用args
,而不要使用sys.argv
。
第二个问题是您正在切片sys.argv[1:]
,但将其视为单个值而不是值列表来对待。
如果要允许通过-d
传递多个目录并对其进行处理,则需要在切片上进行for arg in …:
循环。
如果只需要一个目录,则只需索引列表,例如[1]
,而不是[1:]
。尽管,如果您愿意的话,您可能不希望-d
是一个布尔型标志,而目录不是arg;您希望-d
是一个以目录作为其值的标志。
更一般而言,您可能首先不应该在这里使用getopt
。正如the docs所说:
注意
getopt
模块是命令行选项的解析器,其API设计为Cgetopt()
函数的用户熟悉。不熟悉Cgetopt()
函数的用户或想编写更少代码并获得更好帮助和错误消息的用户,应考虑使用argparse
模块。
如果您是getopt
向导,那么可以肯定的是,即使简单更好,也可以将getopt
用于简单项目,而不要学习新知识。但是对于其他任何人,实际上没有充分的理由首先学习getopt
,更不用说学习如何调试它的所有时髦之处了。 argparse
在各方面都变得更好。而且,如果您不喜欢argparse
,则PyPI上有六种替代方法。