2013-07-11 108 views
6

我已閱讀多篇文章和許多文章詳細介紹了在cron作業scipts需要保持必要的環境變量的腳本內部運行,由於cron的內殼的開放。我的情況是獨一無二的,因爲我的路徑變量都是按照討論設置的,而這些變量反過來會使用subprocess.call()成功調用pysaunter python egg,但它似乎從那裏分解了。這導致整個過程在cron作業中被打破。的Python腳本不能在crontab中運行調用pysaunter

爲了清楚起見,這裏是我指的是以下步驟:

1) cronjob calls run_test.py -n foo 
2) run_test.py sets the environment variables correctly 
(cur_shell_path=sys.path (converted to proper path string, not shown here) 
my_env= os.environ.copy() 
my_env["PATH"] = my_env["PATH"] + cur_shell_path) 
3) run_test.py calls subprocess.call("pysaunter -m foo -v", env=my_env, shell=True) 

步驟3的輸出表明,它是找到雞蛋,併成功地開始加載從pysaunter必要的模塊,但隨後它打破時試圖找到一個用於修改pysaunter的目錄。錯誤如下:

ImportError: no module named helpers 

我試圖向環境多次添加此路徑,但它似乎從未找到包含helpers.py的目錄。當從交互式shell中調用時,命令pysaunter -m foo -v正常工作。

我找不到上pysaunter太大的幫助,所以我認爲太多pysaunter細節是不必要在這裏。如果您對pysaunter瞭解更多,請告訴我是否需要更多信息。我不知道要分享什麼。

我也看了很多帖子討論通過編輯.profile文件/ .bash_profile中改變外殼的默認行爲的能力。我試圖找到一個能讓我的路徑變量全局可訪問的地方,但我找不到任何東西。我不確定這是如何完成的,它可能會解決我的問題,所以如果你對此有所瞭解,請告訴我。

最後說明,這是在Mac 10.7.5上運行。

回答

3

多的試驗和錯誤,以及許多stackoverflow.com文章和其他教程後在線,並在Perl腳本的幫助下,我發現做了類似的事情,我能夠弄清楚需要做些什麼才能使其發揮作用。

以下是具體步驟,以確保一切設置正確:

  1. 請確保您有你PYTHONPATH所需要的變量(發現herehere,以及更多的信息去here)內.profile或.bash_profile用於任何你想測試腳本的shell,以確保它能正常工作。

  2. 編輯你的crontab包含運行在一個cron作業你 腳本所需要的目錄(發現herehere)。

    a)請確保將根目錄包含在PATH變量(。)中,如here所述。基本上,如果你用你的命令運行一個可執行文件,它需要能夠找到根或存儲可執行文件的目錄,也可能是這些:(/ sbin:/ bin:/ usr/sbin:/ usr/bin)。

  3. 在您的crontab文件中,創建一個cronjob,將當前目錄更改爲您之前成功運行腳本的目錄(例如,/ Users/user/Documents/foo)。

    一)這將如下所示:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v 
    
  4. 因爲我的問題與調用可執行具體處理,有必要注意,有寫的Python腳本運行的多種方式(儘管在發現過程中,我瞭解到,這對於在cron中使用子進程進行的任何調用都適用)。

    第一種方法是這樣的:

    ... #some script calls 
    my_env = os.environ.copy() 
    my_env["PYTHONPATH"] = "{}:{}".format(os.environ["PATH"] ,"<path you want to include>") 
    os.chdir("<path/to/desired/directory>") 
    subprocess.Popen(<call_as_string>, env=my_env, shell=True) 
    

    而第二個看起來像這樣:

    ... #some script calls 
    os.environ["PYTHONPATH"] = "{}:{}".format(os.environ["PATH"] ,"<path you want to include>") 
    os.chdir("<path/to/desired/directory>") 
    subprocess.Popen(<call_as_list_of_arguments) 
    

    由於可執行文件所需的路徑傭工目錄包括在殼中它被稱爲從,有必要將環境變量傳遞給可執行文件,如here所述。但是,我發現修改環境中的PATH變量對於cron作業不起作用,但是設置PYTHONPATH卻行。我讀了here,shell使用PATH變量只查找可執行文件,因此對於cronjob中的新shell,需要將shell傳遞給PYTHONPATH以查找新的Python模塊。 (這也是explained in the Python docs。)

    兩個不同方法之間的差異在問題中引用的子流程文檔中有所解釋,但可以找到有關此模塊的良好教程here

1

你所說的沒有意義。

你說shell_env = sys.pathsys.path是用於查找模塊的python文件夾列表,而不是環境變量映射!

您然後使用在subprocess.call。也許你打算寫env=my_env

這就是下一個問題。首先,PATH應該是由':'分隔的文件夾列表。你只需將shell_path粘貼到最後一個文件夾上即可。

最後,Python使用PYTHONPATH作爲一個列表來查找Python模塊(這似乎是你有什麼問題。)

+1

感謝您指出我的問題,我現在已經修正它顯示my_env正在通過。此外,在基於Unix的機器上,冒號(:)用於分隔路徑值,因此不會成爲問題。最後,Pythonpath用於搜索本地目錄,Unix上的本地目錄由shell的啓動位置(http://docs.python.org/release/1.5.1p1/tut/searchPath.html)定義。由於cron作業調用的非交互式shell不是從正確的目錄啓動的,也不會讀取.profile或.bash_profile,因此不會添加任何路徑,因此不會設置Pythonpath。 – derigible

+1

你對結腸是正確的。我修正了這一點。您需要在cron作業中設置PYTHONPATH。您可以創建一個包裝腳本,將PYTHONPATH設置爲所需的目錄,然後調用python腳本。 – korylprince