簡體   English   中英

使用python csv模塊創建安裝bash腳本

[英]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文件時,出現錯誤bash: ./install_programs: /bin/bash^M: bad interpreter: No such file or directory

如果我擦除所有內容,直到第一個apt-get ..行,並添加bash擴展名“ .sh”,則解釋器會識別它。

  • 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

  • 我的最后一個奧秘是,即使我手動修復了所有這些問題,執行腳本后,即使命令正確,它也不會安裝任何程序,並且如果在終端中使用它們也可以工作。

我得到這樣的輸出:

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\\rif匹配,或者導致您嘗試安裝名為'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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM