2013-02-22 79 views
3

我需要裝運使用多個存儲在本地Library目錄Python程序的集合:我們的目標是避免使用我的程序(包運在Library目錄)之前有用戶安裝軟件包。導入Library中包含的軟件包的最佳方式是什麼?Python包的本地集合:導入它們的最佳方式?

我嘗試了三種方法,但沒有一個看起來很完美:是否有更簡單和更健壯的方法?或者是最好的方法之一?

  1. 在第一種方法中,Library文件夾被簡單地添加到庫路徑:

    import sys 
    import os 
    sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'Library')) 
    
    import package_from_Library 
    

    Library文件夾在一開始就把以便隨我的程序包的優先級高於用戶安裝了相同的模塊(這種方式我確信他們有正確的版本來處理我的程序)。當Library文件夾不在當前目錄中時,此方法也適用,這很好。但是,這種方法有缺點。我的每一個程序都會將相同路徑的副本添加到sys.path,這是一種浪費。另外,所有程序都必須包含相同的三條路徑修改線,這違反了不重複自己原則。

  2. 了上述問題的改進在於嘗試添加Library路徑只有一次,通過導入模塊,做到了這一點:

    # In module add_Library_path: 
    sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'Library')) 
    

    ,然後使用,在我的每個節目:

    import add_Library_path 
    import package_from_Library 
    

    這樣一來,由於CPython中的緩存機制,模塊add_Library_path只運行一次,Library路徑只加一次到sys.path。然而,這種方法的一個缺點是import add_Library_path有一個看不見的副作用,並且導入的順序很重要:這使得代碼更清晰易讀,更脆弱。此外,這迫使我的程序分發,以包括用戶不會使用的add_Library_path.py程序。

    from Library import module_from_Library 
    

    然而,這打破了中:

  3. 的Python 模塊Library也可以通過使其成爲一個包(空__init__.py文件中存儲的),它允許一個做進口Library,因爲他們可能會做類似from xlutils.filter import …,因爲xlutils未在sys.path中找到而中斷。所以,這種方法的工作原理,但只有在Library包括模塊,而不是包。

所有這些方法都有一些缺點。

是否有一種更好的方式來運送儲存在本地Library目錄中的軟件包集合(它們使用)的程序?或者是上述方法之一(方法1?),最好的方法是?

PS:就我而言,Library的所有軟件包都是純Python軟件包,但是適用於任何操作系統的更通用的解決方案是最好的。

PPS:我們的目標是使用戶能夠使用我的程序,而無需安裝任何東西(除了複製我經常把它們運的目錄),如上面的例子。

PPPS:更確切地說,我們的目標是有容易更新兩個我收藏的節目和來自Library及其相關的第三方軟件包的靈活性,通過讓我的用戶做一個目錄的簡單複製包含我的程序和「隱藏」第三方軟件包的文件夾Library。 (我做頻繁的更新,所以我不想迫使用戶更新他們的Python發行過。)

+0

Linux?視窗? – LtWorf 2013-02-22 14:56:37

+0

任何操作系統! – EOL 2013-02-22 23:47:09

回答

2

sys.path()亂搞導致疼痛...的modern package templateDistribute包含的信息繁多,並有一部分被設置以解決您的問題。

我所要做的就是設置setup.py,將所有軟件包安裝到特定的站點包位置,或者如果您可以將其安裝到系統的站點包。在前一種情況下,本地站點包將被添加到系統/用戶的PYTHONPATH中。在後一種情況下,不需要更改

您也可以使用批處理文件來設置python路徑。或者將python可執行文件更改爲指向包含修改的PYTHONPATH的shell腳本,然後執行python解釋器。後者當然意味着你必須有權訪問用戶的機器,而你不需要。但是,如果你的用戶只運行腳本,不導入自己的圖書館,你可以使用自己的包裝器腳本:

#!/path/to/my/python 

而且/path/to/my/python腳本會是這樣的:

#!/bin/sh 
PYTHONPATH=/whatever/lib/path:$PYTHONPATH /usr/bin/python $* 
+0

我增加了兩個PS兩個問題來說明問題,我不希望用戶必須做任何事情(比如在我給出的解決方案中)。 – EOL 2013-02-23 00:11:29

+0

不幸的是,我不能訪問用戶的計算機,因爲我將它們「運」到程序中(並且,我正在尋找一種無需執行任何操作的解決方案)。 – EOL 2013-02-25 12:37:47

+0

+1的評論!好問題。 :)我實際上也特別推出了Python,並安裝了一些模塊(用於他們的平臺);他們通過一個簡單的副本「安裝」它。他們通過設置命令路徑的批處理文件訪問我的程序,以便他們在運行python命令時使用運送的python。我不想過於頻繁地觸摸這個Python +基本模塊的安裝,因爲它更新它是麻煩的。相反,我想根據我的程序的後續版本的需要,將一些簡單的附加軟件包「隱藏」在本地「庫」文件夾中。 – EOL 2013-02-25 12:46:45

1

我想你應該看看path import hooks,它允許在搜索模塊時修改python的行爲。

例如,您可以嘗試像kde的scriptengine那樣爲python插件做些事情[1]。 它增加了一個特殊的標記sys.path(如"<plasmaXXXXXX>"XXXXXX是一個隨機數,只是爲了避免名稱衝突),然後當python試圖導入模塊,並找不到他們在其他路徑,它會打電話給你的進口商,可以處理用它。

一個簡單的替代方法是將主腳本用作啓動程序,它簡單地將路徑添加到sys.path並執行目標文件(以便您可以安全地避免將sys.path.append(...)行放在每個文件上)。

另一個替代方案,它適用於python2.6 +,將安裝在每個用戶site-packages目錄下的庫。


[1]您可以使用kde在linux安裝下找到/usr/share/kde4/apps/plasma_scriptengine_python下的源代碼。

+0

導入掛鉤頁面很有趣,謝謝!我在問題中添加了兩個PS以使其更加精確。 – EOL 2013-02-23 00:09:13