Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
易于使用的(?)函数通过ini文件、命令行和程序名将几乎任何参数输入python_Python_Command Line Arguments_Ini - Fatal编程技术网

易于使用的(?)函数通过ini文件、命令行和程序名将几乎任何参数输入python

易于使用的(?)函数通过ini文件、命令行和程序名将几乎任何参数输入python,python,command-line-arguments,ini,Python,Command Line Arguments,Ini,我试图编写一个函数集,以不同的方式获取参数,并将它们组合起来。一切都可以,但不必设置。 在德语中,我称之为“Eierlegendewollmilchsau”。 代码中有更深入的文档,但是für易于使用,请尝试一下。生成一个设置文件,如setting.ini,其中包含: Animal: dog, cat, mouse Animal: elephant Meaningoflive: 42 Sourcefile: *.py Animal: lion Animals: bears, "some

我试图编写一个函数集,以不同的方式获取参数,并将它们组合起来。一切都可以,但不必设置。 在德语中,我称之为“Eierlegendewollmilchsau”。 代码中有更深入的文档,但是für易于使用,请尝试一下。生成一个设置文件,如setting.ini,其中包含:

Animal: dog, cat, mouse
Animal: elephant
Meaningoflive: 42
Sourcefile: *.py
Animal: lion
Animals: bears, "some snakes", fish
#Fun, isn't it?
并致电:

grabparameter.py setting.ini

或(*.ini不需要键“ini”)

grabparameter.py ini=setting.txt

稍后您将看到,任何参数都可以通过命令行给定,如:

grabparameter.py动物:dog,cat Fun=python,c#,自动热键

甚至通过修改文件名,如:

grabparameter(Animal=dog,cat-Fun=python,c#,autoHotKey).py

字符“%”、“'”和“'=(”)可用于将空格或“,”保留在一个值中。 如果要在文件名中使用路径,请像

grabparameter(c#data#project42#setting.ini).py

如果足够好的话,有什么评论或提示可以放在哪里

来自慕尼黑的问候

import re
import sys
import os
from pathlib import Path

def extendedSplit(toSplit, splitter, quotationChars):
# done 2020 by Detman
# Splits a string (toSplit) in an array of substrings with the char(splitter)
# quotationChars is an array of char (or a string => haha, did not recognized it from the beginning).
# Every substring is trimmed unless spaces are quoted by one of the chars of quotationsChars.
# Any quotation has to be closed by the char of the beginning, after that the quotation char can be switched.
# In between of an quotation the other quotation chars will be used as normal chars.
# to get a quotation char without quotation or the used quotation char itself, write it twice.
# Some examples:
# extendedSplit(" dog , cat , mouse ", ",", "") will result in ['dog', 'cat', 'mouse']
# extendedSplit("dog, %cat, %, mouse, per%%ent" , ",", "%") will result in ['dog', 'cat, ', 'mouse', 'per%ent']
# extendedSplit("Peter''s, cat, is, \"a kind of 'special' cat\"" , ",", {"'", '"'}) will result in ["Peter's", 'cat', 'is', "a kind of 'special' cat"]
    parts = []
    part = ""
    inQuotation = False
    inQuotationCharacter = ""
    spaceKeeper = ""
    inQuotationCharacterJustBefore = False
    for character in toSplit:
        if character == inQuotationCharacter:
            if inQuotationCharacterJustBefore:
                part += spaceKeeper + character
                spaceKeeper = ""
                inQuotationCharacterJustBefore = False
            else:
                inQuotationCharacterJustBefore = True
            inQuotation = not inQuotation
        elif (character in quotationChars) and not inQuotation:
            inQuotationCharacter = character
            inQuotationCharacterJustBefore = True
            inQuotation = True
        elif character == splitter and (not inQuotation):
            parts.append(part)
            part = ""
            spaceKeeper = ""
            inQuotationCharacter = ""
        elif character != " " or inQuotation:
            part += spaceKeeper + character
            spaceKeeper = ""
            inQuotationCharacterJustBefore = False
        elif character == " " and (not inQuotation) and len(part) > 0:
            spaceKeeper += character
    if len(part) > 0:
        parts.append(part)
    return parts

def readParameterLine(parameter, line):
# done 2020 by Detman
# Interpretes a string(line) and appends its values of line to a dictionary at key.
# The format of line is "Key=Value1,Value2, Value3, etc."
# e.g.: line = "Animals=dog, cat, mouse" will create a key "Animals" at parameter with the array ['dog', 'cat', 'mouse']
# e.g.: if there is already a key "Animals", then the additional array will be appende to the key.
# Some more specialities, line will always be trimmed at first, then:
# starting characters "/" and "-" will be ignored, so, you can use them like "/Animals:Elephant" or leave them away.
# starting with "#" will add everything whith out the leading "#" to a key "Comment"
# As split character the "=" and ":" can be used. "Animals=dog, ..." or "Animals:dog, ..."
# If there is no split character at all, but the line ends with ".ini", the line will be appended to the key "Ini" of parameter.
# If there is no split character at all, but the line ends not with ".ini", the line will be appended to the key "ErrorEntry" of parameter.
# The dictionary key will always be set to "title()" like "cars" or "CARS" => "Cars", "nameSurname" => "Namesurname"
    line = line.strip()
    if len(line) > 0:
        if line[0] == "/" or line[0] == "-":
            line = line[1:]
        if line[0] == "#":
            if not ("Comment" in parameter.keys()):
                parameter.update({"Comment" : []})
            parameter["Comment"].append(line[1:])
        else:
            match = re.search("(.*?)[\:|=](.*$)", line)
            if match:
                left = match.group(1).strip().title()
                right = match.group(2).strip()
                list = extendedSplit(right, ",", {"'", '"', "%"})
                for l in list:
                    if not (left in parameter.keys()):
                        parameter.update({left : []})
                    parameter[left].append(l.strip())
            elif line[-4:].lower() == ".ini":
                if not ("Ini" in parameter.keys()):
                    parameter.update({"Ini" : []})
                parameter["Ini"].append(line)
            else:
                if not ("ErrorEntry" in parameter.keys()):
                    parameter.update({"ErrorEntry" : []})
                parameter["ErrorEntry"].append(line)
    return

def unmaskFilePath(filePath, mask):
# done 2020 by Detman
# In file names the chars "\" and ":" are not allowed. Instead of them they are masked e.g. by a "#".
# e.g.: unmaskFilePath("c#data#projectx#project.ini", "#") will result: "c:\data\projectx\project.ini"
    filePath = re.sub("(^[a-z|A-Z])" + mask, "\\g<1>:\\\\", filePath)
    filePath = re.sub(mask, "\\\\", filePath)
    return filePath

def grabParameterFromAllInputs(parameter):
# done 2020 by Detman
# Here is the "Pudels Kern"!
# The dictonary "parameters" will be filled by parameter from all sources
# a) Parameter can be commited by the file name itself, the paramater must be set into barckets like:
# myprogram(Greetings=Hello,Hi,%Have a nice day%, Otherparam=42 morevalues.ini).py => the result in parameter is:
# {'Greetings': ['Hello', 'Hi', 'Have a nice day'], 'Otherparam': ['42'], 'Ini': ['morevalues.ini'], 'ErrorIniFile': ['morevalues.ini']}
# In my test, there was no file "morevalues.ini".
# b) Parameter can be commited by command line,like: myprogram.py Animals:dog,cat,mouse "Greeting:Hi, Hello, Have a nice day" ini=somevalues.txt
# {'Animals': ['dog', 'cat', 'mouse'], 'Greeting': ['Hi', 'Hello', 'Have a nice day'], 'Ini': ['somevalues.txt'], 'ErrorIniFile': ['somevalues.txt']}
# c) Parameter can be commited by ini-File. As long as there are unread files in the array of parameter["Ini"] the files are tried to read and interpreted.
# It is allowed to mention a key more than one time, even in one File. The value(s) will always be appended to the key.
# Following this logic, ini-Files can be cascaded, as long as there are unread parmeter["Ini"] entries, the entries will be included.
    result = True
    inQuotationParameter = re.search("\((.*)\)",sys.argv[0])
    if inQuotationParameter:
        inQuotationlist = extendedSplit(inQuotationParameter.group(1)," ", {"%"})
        for inQuotationParam in inQuotationlist:
            readParameterLine(parameter, inQuotationParam)
        if "Ini" in parameter.keys():
            for iniEntry in range(0, len(parameter["Ini"])):
                parameter["Ini"][iniEntry] = unmaskFilePath(parameter["Ini"][iniEntry], "#")
    for sysArgvEntry in range(1, len(sys.argv)):
        readParameterLine(parameter, sys.argv[sysArgvEntry])
    if "Ini" in parameter:
        iniEntry = 0
        while len(parameter["Ini"]) > iniEntry:
            if Path(parameter["Ini"][iniEntry]).is_file():
                iniFile = open(parameter["Ini"][iniEntry], 'r')
                lines = iniFile.readlines() 
                iniFile.close()
                for line in lines:
                    readParameterLine(parameter, line)
            else:
                if not ("ErrorIniFile" in parameter.keys()):
                    parameter.update({"ErrorIniFile" : []})
                parameter["ErrorIniFile"].append(parameter["Ini"][iniEntry])
            iniEntry += 1
    else:
        result = False
    return result

def fileAsteriskSubstitude(parameter, source, destination):
# done 2020 by Detman
# Some more magic.
# Any key in parameter can be interpreted as file name (with path information if needed).
# It is allowed to use the asterisk as usual know on command line.
# Every entry with the key "source" will be solved by "*" to a list of files and then every file is checked of existance.
# Every exiting file, matching to "*" or with dedicated name will be appended to the entry "destination"
# myprogram.py Sourcefile=*.ini SourceFile=*.txt SourceFile=ttt.py  will peron on my folder like:
# {'Sourcefile': ['*.ini', '*.txt', 'ttt.py'], 'SourceFile': ['myfile2.iNi', 'log.txt', 'myfile2.txt', 'ttt.py']}
# Nice Twist: As readParameterLine converts all key to .title(), the key "SourceFile" can not be set manually by user.
if source in parameter.keys():
    for lauf in range(0, len(parameter[source])):
        pathFile = parameter[source][lauf]
        pathSearch = re.search("(.*\\\\)(.*)", pathFile)
        if pathSearch:
            path = pathSearch.group(1)
            if os.path.isdir(path):
                fileName = pathSearch.group(2)
                files = [file for file in os.listdir(path) if os.path.isfile(os.path.join(path, file))]
            else:
                files = []
                fileName = ""
        else:
            fileName = pathFile
            path = ""
            files = [file for file in os.listdir() if os.path.isfile(file)]
        searchAsterisk = re.sub("([]\\\\.\\\\^\\\\$\\\\+\\\\{\\\\}\\\\|[\\\\(\\\\)])", "\\\\\\g<1>", fileName)
        searchAsterisk = re.sub("\\*", ".*", searchAsterisk)
        for file in files:
            if re.search(searchAsterisk, file, re.IGNORECASE):
                if not (destination in parameter.keys()):
                    parameter.update({destination : []})
                parameter[destination].append(path + file)
return

def uniqueArray(array):
# done 2020 by Detman
# There is a function in python to give back unique entries, but python muddles the values.
# This funktion keep the order of every value and deletes double entries in later positions. 
    tempArray = []
    tempDict = {}
    for element in array:
        if not (element in tempDict):
            tempDict[element] = True
            tempArray.append(element)
    return tempArray

def uniqueEnrtriesPerParameter(parameter):
# done 2020 by Detman
# Last step, clear the value lists of all keys.
# keep in mind, the first entry parameter[key][0] committed in the order of FILENAME(paramater), command line and them all ini-Files should be the best one.
    for left in parameter:
        parameter[left] = uniqueArray(parameter[left])
    return

def grabParameter():
# done 2020 by Detman
# For a closer look, check functions above.
    parameter = {}
    grabParameterFromAllInputs(parameter)
    fileAsteriskSubstitude(parameter, "Sourcefile", "SourceFile")
    uniqueEnrtriesPerParameter(parameter)
    return parameter


print("Start")
print()

parameter = grabParameter()
print(parameter)

print(".")
print("Ende")
重新导入
导入系统
导入操作系统
从pathlib导入路径
def extendedSplit(toSplit、Spliter、quotationChars):
#德特曼于2020年完成
#使用char(拆分器)拆分子字符串数组中的字符串(toSplit)
#quotationChars是一个字符数组(或者一个字符串=>haha,从一开始就没有识别它)。
#除非空格被quotationsChars中的一个字符引用,否则每个子字符串都会被修剪。
#任何报价都必须以开头的字符结束,然后才能切换报价字符。
#在报价之间,其他报价字符将用作普通字符。
#要获取不带引号的引号字符或已使用的引号字符本身,请编写两次。
#一些例子:
#extendedSplit(“dog,cat,mouse”,,,,,”)将导致['dog','cat','mouse']
#extendedSplit(“狗、%cat、%、鼠标、每%%ent”、“、”、“%”)将导致['dog'、'cat'、'mouse'、'per%ent']
#extendedSplit(“Peter’s,cat,is,\“一种‘特殊’cat\”,“,”,{“,”})将导致[“Peter’,‘cat’,‘is’,‘一种‘特殊’cat”]
部分=[]
part=“”
inquote=False
inQuotationCharacter=“”
太空人=“”
inQuotationCharacterJustBefore=False
对于toSplit中的字符:
如果字符==inQuotationCharacter:
如果InQuotationCharacter恰好位于以下位置之前:
零件+=太空人+角色
太空人=“”
inQuotationCharacterJustBefore=False
其他:
inQuotationCharacterJustBefore=真
inquote=不inquote
elif(引用字符中的字符)和非引用字符:
inQuotationCharacter=字符
inQuotationCharacterJustBefore=真
inquote=True
elif字符==拆分器和(不在引号中):
部分。附加(部分)
part=“”
太空人=“”
inQuotationCharacter=“”
elif字符!=“”或引号:
零件+=太空人+角色
太空人=“”
inQuotationCharacterJustBefore=False
elif字符==“”和(不在引号中)以及len(部分)>0:
太空人+=字符
如果len(零件)>0:
部分。附加(部分)
返回部件
def readParameterLine(参数,行):
#德特曼于2020年完成
#解释字符串(行)并将其行值附加到字典的键处。
#行的格式为“Key=Value1、Value2、Value3等”
#例如:line=“Animals=dog,cat,mouse”将在参数处创建一个键“Animals”,数组为['dog','cat','mouse']
#例如:如果已经有一个键“Animals”,那么额外的数组将附加到该键。
#还有一些特色菜,首先将始终修剪线条,然后:
#起始字符“/”和“-”将被忽略,因此,您可以像“/Animals:Elephant”一样使用它们,或者将它们忽略。
#以“#”开头将把所有带前导“#”的内容添加到键“注释”中
#可以使用“=”和“:”作为拆分字符。“动物=狗,…”或“动物:狗,…”
#如果根本没有拆分字符,但行以“.ini”结尾,则该行将附加到参数的键“ini”上。
#如果根本没有拆分字符,但行的结尾不是“.ini”,则该行将附加到参数的键“ErrorEntry”上。
#字典键将始终设置为“title()”,如“cars”或“cars”=>“cars”,“nameurname”=>“nameurname”
line=line.strip()
如果len(线)>0:
如果第[0]==“/”行或第[0]==“-”:
行=行[1:]
如果第[0]行=“#”:
如果没有(parameter.keys()中的“注释”):
parameter.update({“Comment”:[]})
参数[“Comment”]。追加(第[1:]行)
其他:
match=re.search(“(.*?[\:|=]”(.*$”,第行)
如果匹配:
左=match.group(1).strip().title()
右=match.group(2).strip()
list=extendedSplit(右“,”,{“,”,“%”})
对于列表中的l:
如果不是(留在parameter.keys()中):
parameter.update({left:[]})
参数[left]。追加(l.strip())
elif行[-4:].lower()==“.ini”:
如果不是(“Ini”在parameter.keys()中):
参数更新({“Ini”:[]})
参数[“Ini”]。追加(行)
其他:
如果没有(parameter.keys()中的“ErrorEntry”):
参数.update({“ErrorEntry”:[]})
参数[“ErrorEntry”]。追加(行)
返回
def unmaskFilePath(文件路径,掩码):
#德特曼于2020年完成
#在文件名中,不允许使用字符“\”和“:”。而不是它们,它们被一个“#”等符号所掩盖。
#例如:unmaskFilePath(“c#data#projectx#project.ini”、“#”)将导致:“c:\data\projectx\project.ini”