2013-08-02 46 views
4

摘要: 我想要一個類型爲'module'的變量並將其導出。導出一個python模塊(到字符串或py文件)

我正在使用導入從.py文件導入python模塊並對其進行更改。我需要將模塊導出回一個文件或獲取可以寫入磁盤的完整模塊的字符串表示。

我一直無法找到任何方式導出Python模塊或方式到模塊中的對象轉換爲字符串結構化,純文本的python-可執行格式。 (未JSON,酸洗等)

詳細問題&使用案例: 這個要求是一個內部構建過程的一部分;沒有安全要求,只有我們自己的模塊,而不是內置模塊,正在修改。一個python腳本運行業務邏輯來修改其他一些腳本。此過程使用僅在構建時可用的信息。因此我沒有選擇在運行時導入具有不同數據的模塊。

初始系統用於與將被替換,但目前的要求需要更復雜的修改對象聲明,其中編程修改對象遠比字符串替換佔位符更容易串的模板。

我已經完成 隨着主發生器腳本,用Python編寫的,我可以導入多個模塊(其中只有變量聲明,沒有可執行代碼),使我需要的所有替換。我留下了一個類型模塊的變量,我需要將其導回到一個文件中以便稍後執行。

@abarnert有一些好的想法。我不知道repr函數。這給了我信息,但沒有任何格式。這讓我看到了pprint,它與我目前爲止所得到的一樣接近。

example.py

sample = { 
    'level1_dict_1' : { 
     'key1' : 'value1', 
     'key2' : { 
      'level2_dict' : { 
       'key1' : 'value3', 
       'key2' : ['list1','list2','list3','list4'], 
      } 
     } 
    }, 
    'level1_dict_2' : { 
     'key1' : 'value1', 
     'key2' : 'value2', 
    }, 
} 

大大簡化(和不應用任何業務邏輯)我基本上要做到以下幾點:

with open("example.py","w") as outfile: 
    example = __import__('example') # Import module 
    example.sample['level1_dict_1']['key2']['level2_dict']['key2'][2] = "newlistitem3" # Change 1 property in a list nested a few levels deep 
    outfile.write("sample = \n" + pprint.pformat(example.sample)) # 

我很想有格式與我的源文件相同,但pprint雖然可讀,但格式不同,我不喜歡。這可能儘可能接近我所需要的。

pprint輸出:

sample = 
{'level1_dict_1': {'key1': 'value1', 
        'key2': {'level2_dict': {'key1': 'value3', 
              'key2': ['list1', 
                'list2', 
                'newlistitem3', 
                'list4']}}}, 
'level1_dict_2': {'key1': 'value1', 'key2': 'value2'}} 

編輯&澄清: - 我的目標是加載模塊,修改它,並保存回爲一個可執行文件的Python。這就是我反對pickle,json等的原因。我需要生成一個可執行的py文件。 - 重寫使用案例的澄清 - 增加的例子和更多的信息,我已經嘗試過

+2

爲什麼你需要導入文件?你不能使用像django這樣的模板系統來從模板中生成自定義的PY文件嗎? – jarmod

+0

或者創建Python文件讀取並從運行時生成對象的_data_文件,而不是嘗試創建Python文件? – abarnert

+0

我認爲這是你正在尋找的東西:http://stackoverflow.com/questions/14163532/is-there-anything-like-python-export – Jocke

回答

3

你要求的是不可能的。您正嘗試從目標代碼中創建源代碼。雖然反編譯器項目可以或多或少地做到這一點,但完全一般的解決方案是棘手的。

如果您只是想將原始源代碼提供給模塊,那很簡單。例如,您可以使用inspect.getsource,然後將結果字符串寫入文件。或者僅使用inspect.getfile並從結果路徑名中複製。

而你當然可以修改原始來源,而複製它。例如:

source = inspect.getsource(foo) 
with open('newfoo.py', 'wb') as f: 
    f.write(source) 
    f.write('spam = Spam(3)\neggs = Eggs(spam)\n') 

但是,您不能修改foo然後重新生成它的源代碼。


但是,有可能有更好的方法來做你真正需要做的事情。例如:

  • 使用JSON,泡菜(模式0),YAML等,儘管你要求什麼,這些都是結構,可讀的純文本格式,就像Python源。使用repr。對於字符串,數字和內置常量文字,以及除上述類型(遞歸)以外都不包含任何內容的列表和字符串,則可以循環訪問repr。例如:


with open('newfoo.py', 'wb') as f: 
    for name, value in foo.__dict__.items(): 
     f.write('{} = {!r}\n'.format(name, value)) 
  • 如果你很確定所有的值都是再版,能幹,但不積極,有許多的方法來檢查或消毒你的輸出在寫出來之前。例如:

with open('newfoo.py', 'wb') as f: 
    for name, value in foo.__dict__.items(): 
     if ast.literal_eval(repr(value)) != value: 
      raise ValueError('Tried to save {}'.format(value)) 
     f.write('{} = {!r}\n'.format(name, value)) 
  • 在一些不錯的格式,這是非常適合你的代碼生成器,人類閱讀器等,而不是試圖產生Python源創建數據文件,然後編寫簡單的Python代碼讀取數據文件並在運行時生成對象。
+0

這是非常有用的,並提到了一些我以前沒有意識到的技術的。我重寫了我的問題,以反映我正在嘗試的內容。我做了一個簡單的例子,而不是長時間的用例。使用這裏指定的技術,我完全可以完成我的任務,即導入模塊,進行更改,然後將每個屬性和內容寫入文件。如果這是儘可能的,那就足夠好了,但是如果有什麼方法可以更好地控制理想的輸出格式。人類手動修改這些文件,而且空白有助於這些。 – Eric

相關問題