2016-05-18 119 views
1

我想將我的程序傳遞給一個文件並從中獲取一個函數。加載沒有模塊的源文件

例如,我有一個文件,foo.py,誰的位置是未知的,直到運行時,可在我的系統上的任何地方,看起來像這樣:

def bar(): 
    return "foobar" 

我如何才能讓我的代碼來運行功能bar

如果該位置是運行時間之前知道我能做到這一點:

import sys 
sys.path.append("path_to_foo") 
import foo 

foo.bar() 

我可以在文件夾中創建一個init.py文件,其中foo.py是和使用importlibimp但似乎凌亂。我不能用__import__我得到ImportError: Import by filename is not supported.

+2

「我可以使用'importlib' [...],但它似乎凌亂。」當你有麻煩的問題時,你必須求助於混亂的解決方案。爲什麼'importlib'不夠? –

+0

另外,你根本不需要'__init __。py'文件。在Py3中,更強大的'importlib'函數是導入任意文件的正確方法。在早期的Python中,只需將包含'foo.py'的文件夾添加到'sys.path',然後運行'import foo'而不需要使用特殊的導入函數。 – ShadowRanger

+0

foo.py與你的文件在同一個目錄下嗎? – NoOneIsHere

回答

2

您可以使用exec打開文件並執行它。

f = open('foo.py') 
source = f.read() 
exec(source) 
print bar() 

你甚至可以尋找使用re

+0

我結束了使用這樣的事情。我其實是'sys.path.append(「path_to_foo」); file_name = foo.py; exec(導入file_name作爲foo); foo.bar()' –

+0

@ R.Mckemey你說過'誰的位置直到運行時才知道,可以在我的系統上的任何地方......'。你將如何找到該文件? – NoOneIsHere

+0

對不起,我不清楚,整個文件路徑會傳遞給程序。我會運行它,像'python program.py path_to_foo/foo.py' –

0

您可以編寫一個虛擬函數,到處叫什麼你需要,繞過檢查:

def bar(): 
    pass 

在運行時覆蓋功能與一個你實際上打算,並自動在任何地方使用。

注意:這比使用importlib更雜亂。

+0

我會如何「覆蓋功能」? –

+0

@ R.Mckemey動態地找出可以使用的函數代碼的位置,'eval'或'exec'來加載/運行你的函數代碼。 – anand

0

如果foo.py是在同一目錄作爲您的主要文件中的特定功能,您可以使用

from . import foo 

(Python 3中)。這是可行的,因爲.是您的文件的目錄,Python將爲您導入同一目錄中的文件。然後,您可以使用

foo.bar() 

如果不是,你需要找到它,然後執行它:

import os 
from os.path import join 

lookfor = "foo.py" 
for root, dirs, files in os.walk('C:\\'): # or '/' for Linux/OSX 
    if lookfor in files: 
     execfile(join(root, lookfor)) # Python 2, or 
     with open(join(root, lookfor)) as file: 
      exec(''.join(file.readlines())) 
     break 
foo.bar() 

積分:Martin Stone。我不只是複製代碼,我理解代碼,並且可以自己做。