2016-11-28 33 views
0

我想通過簡單的方法來更新我正在使用的程序,只需將替換.py文件放在一個文件夾中,然後再將它放在sys的頂部即可。所以所有導入語句將首先檢查該文件夾而不是我的頂級目錄,導入新的.py文件,而不是最初用PyInstaller構建程序的文件。現在,如果我用這個代碼:Pyinstaller程序中的模塊導入優先

import sys,os 
    bundlePath = 'c:/tests/importTest' 
    print ("Bundle path: {}".format(bundlePath)) 
    importPath = bundlePath + '/uploads' 
    sys.path.insert(0,importPath) 
    print ("Import path: {}".format(sys.path[0])) 
    os.chdir(sys.path[0]) 
    import testyTastery 
    print(testyTastery.message) 

我的Python IDE或運行此腳本通過命令行來將打印從uploads/testyTastery.py消息(也有testyTastery.py在頂級目錄)。但是,當我將第2行更改爲bundlePath = sys.path[1](因爲PyInstaller中的構建將頂級目錄放在sys.path [1]中,至少在Windows中,sys.path [0]指向PyInstaller創建的base_library.zip)並構建這到PyInstaller的文件夾包中(確保複製uploads/testyTastery.py或將其包含在.spec文件中),我從testyTastery.py腳本獲取消息,而不是uploads/testyTastery.py腳本。

關於如何輕易改變這個的任何想法?清楚的是,前兩個打印語句導致相同的輸出,用於在使用PyInstaller編譯之前和之後運行它,如上所述更改第二行之後。

我不知道,但也許它與PyInstaller總是在查看sys.path中的導入之前查看它打包的文件有關?

編輯:爲了清楚起見,如果我在沒有可用文件的情況下進行編譯,然後將這些文件放入適當的文件夾中,那麼導入優先級就像在命令行/ IDE中一樣。這表明由PyInstaller打包的文件在導入層次結構中較高。

+0

如果你正在構建'--onedir',你可以運行'pyinstaller'來生成更新.pyd文件並複製和替換舊的。只要確保這個工作在分發「拍」之前CH」。 – Repiklis

+0

感謝您的建議;我相信它對於其他人以及未來可能會派上用場。 我正在尋找一種方法來儘可能地用最少的數據推送更新,而您的建議將意味着大約10mb的數據與1-100kb的更新相比較,這些數據加起來很快,特別是與我計劃分發的方式更新(作爲通過ØMQ的直接轉賬)。 –

+0

如果您不關心代碼向用戶公開的事實,則可以使用.py或.pyc文件替換.pyd。它仍然有效。 – Repiklis

回答

0

我終於找到了解決這個問題的辦法。要清楚的是,最初的問題是用PyInstaller打包文件(在文件夾選項中),後來只是放入文件來替換原來打包的文件。由於PyInstaller會將其加載文件的方法插入到sys.meta_path中,因此您需要在PyInstaller之前安裝自定義的導入方法。這是我得到的(更改系統路徑的順序是因爲PyInstaller也將sys.path [0]更改爲一個zip文件,sys.path [1]是您真正想要在sys的頂部。如果你正在做這個或在程序中使用的sys.path [0]路徑鏈:

import os 
import sys 
sys.path = [sys.path[1]] + [sys.path[0]] + sys.path[2:] 
from importlib.machinery import SourceFileLoader 

class MyImporter(object): 
    def find_module(self, module_name, package_path): 
     print ('entered again') 
     if os.path.exists("{}/{}.py".format(sys.path[0],module_name)): 
      return SourceFileLoader(module_name,"{}/{}.py".format(sys.path[0],module_name)) 
     else: 
      return None 
    def load_module(self, module_name): 
     if os.path.exists("{}/{}.py".format(sys.path[0],module_name)): 
      return SourceFileLoader(module_name,"{}/{}.py".format(sys.path[0],module_name)).load_module() 
     else: 
      return None 
sys.meta_path.insert(1,MyImporter()) 

如果你這樣做在你的主文件PyInstaller進口則整個程序將搜索的sys.path [0](在搜索PyInstaller打包模塊之前,添加更多的文件夾到你的系統路徑並搜索它們也是微不足道的。)