[英]Creating an installation bash script with the python csv module
以下代碼應為我提供“有效的bash腳本”
box_category=GET_COMBOBOX_value(self,self.combobox_category2,False)
list_path=Data_Location+"/program-data/programs_to_install.csv"
list=csv.reader(open(list_path),delimiter='|')
bash_file=path+"/install_programs"
if os.path.exists(bash_file):
os.remove(bash_file)
with open(bash_file, "ab") as f:
bash_list=csv.writer(f,delimiter='|')
bash_list.writerow(["#!/bin/bash"])
bash_list.writerow([" "])
string="if [ \"$(id -u)\" != \"0\" ]; then echo \"You need root permission for installing programs.\" 1>&2; exit 1; fi"
print string
bash_list.writerow([string])
for row in list :
bash_list.writerow(["apt-get --yes install "+row[0]])
time.sleep(0.2)
os.system("chmod a+x '"+bash_file+"'")
乍一看,它幾乎“正確”,它為我生成了這個bash文件:
#!/bin/bash
"if [ ""$(id -u)"" != ""0"" ]; then echo ""You need root permission for installing programs."" 1>&2; exit 1; fi"
apt-get --yes install 0ad
apt-get --yes install audacity
apt-get --yes install banshee
apt-get --yes install barrage
..etc..
但:
bash: ./install_programs: /bin/bash^M: bad interpreter: No such file or directory
如果我擦除所有內容,直到第一個apt-get ..
行,並添加bash擴展名“ .sh”,則解釋器會識別它。
"if [ \\"$(id -u)\\" != \\"0\\" ]; then echo \\"You need root permission for installing programs.\\" 1>&2; exit 1; fi"
它應該寫為:
if [ "$(id -u)" != "0" ]; then echo "You need root permission for installing programs." 1>&2; exit 1; fi
我得到這樣的輸出:
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package 0ad
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package audacity
Reading package lists... Done
Building dependency tree
Reading state information... Done
CSV的全部要點是它是用逗號分隔的值表示的-也就是說,每行有多列,用逗號分隔。 這意味着,如果您的任何值中恰好有逗號,則必須將其引用(或轉義)。 這些引號規則意味着,如果您的任何值中恰好有引號字符,則必須對該值進行引號處理。 因此,代替此:
if [ "$(id -u)" != "0" ]; then echo "You need root permission for installing programs." 1>&2; exit 1; fi
…您最終得到了:
"if [ ""$(id -u)"" != ""0"" ]; then echo ""You need root permission for installing programs."" 1>&2; exit 1; fi"
當然,這不是有效的bash命令。
簡單的解決方案是不使用csv
模塊。 只需將您的行寫到文件中,而不是嘗試將每一行都變成csv
模塊編寫的一列列表,以期獲得所需的行。
with open(bash_file, "a") as f:
f.write("#!/bin/bash\n")
f.write(" \n")
string="if [ \"$(id -u)\" != \"0\" ]; then echo \"You need root permission for installing programs.\" 1>&2; exit 1; fi"
print string
f.write(string + "\n")
for row in list:
f.write("apt-get --yes install " + row[0] + "\n")
如果您厭倦了全部鍵入所有這些顯式換行符,則可以將write
函數包裝起來:
def writeline(f, line):
f.write(line + '\n')
然后,無論您在哪里進行此操作:
f.write(string + "\n")
…您可以改為:
writeline(f, string)
這可能是個好主意。 否則,您將忘記一行上的“ \\ n”,或者更糟糕的是,鍵入錯誤,並花一個小時調試您的代碼,無論您盯着它多少,這顯然都是正確的,但仍然無法正常工作…
這個錯誤:
bash: ./install_programs: /bin/bash^M: bad interpreter: No such file or directory
… 也是由使用csv
模塊引起的。
默認的CSV方言使用Windows風格的換行符-即,每行以'\\r\\n'
結尾。 (請參閱文檔中的Dialect.lineterminator
。)但是bash
Unix風格的換行符-也就是說,每行以'\\n'
結尾。 因此,它將多余的'\\r'
視為實際行的一部分。 因此,在shebang行上,它認為您想要'/bin/bash\\r'
而不是想讓'/bin/bash'
作為解釋器,這是一個完全有效的文件名,但是沒有該名稱的文件。
您的最后一個問題很可能是完全相同的問題。 額外的不可見的'\\r'
字符可能會阻止fi\\r
與if
匹配,或者導致您嘗試安裝名為'0ad\\r'
而不是'0ad'
,等等。
一些注意事項:
list
; 隱藏您可能要使用的同名的內置類型/函數。 另外,盡管出現的次數較少,但string
是stdlib模塊的名稱,因此通常也不要這樣做。 """if [ "$(id -u)" != "0" ]; then echo "You need root permission for installing programs." 1>&2; exit 1; fi"""
第一條線索可能在"^M"
。 這是回車,並且shebang執行機制將其視為可執行路徑的一部分。 未經適當清理,請勿在其他環境中使用在Windows中創建的文本文件。 您仍然可以通過使用sh
來運行腳本來克服這一問題。 正如@abarnert在他/她的答案中指出的那樣, csv
模塊不是輸出所必需的,並且確實妨礙了它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.