簡體   English   中英

如何導入其他 Python 文件?

[英]How do I import other Python files?

如何在 Python 中導入文件? 我要導入:

  1. 一個文件(例如file.py
  2. 一個文件夾
  3. 根據用戶輸入在運行時動態生成文件
  4. 文件的一個特定部分(例如單個函數)

導入 python 文件的方法有很多種,各有優缺點。

不要匆忙選擇第一個適合您的導入策略,否則當您發現它不滿足您的需求時,您將不得不重寫代碼庫。

我將開始解釋最簡單的示例#1,然后我將轉向最專業和最強大的示例#7

示例 1,使用 python 解釋器導入 python 模塊:

  1. 把它放在 /home/el/foo/fox.py 中:

     def what_does_the_fox_say(): print("vixens cry")
  2. 進入python解釋器:

     el@apollo:/home/el/foo$ python Python 2.7.3 (default, Sep 26 2013, 20:03:06) >>> import fox >>> fox.what_does_the_fox_say() vixens cry >>>

    您通過 python 解釋器導入了 fox,從 fox.py 中調用了 python 函數what_does_the_fox_say()

示例 2,在腳本中使用execfile或( Python 3 中的exec )來執行其他 python 文件:

  1. 把它放在 /home/el/foo2/mylib.py 中:

     def moobar(): print("hi")
  2. 把它放在 /home/el/foo2/main.py 中:

     execfile("/home/el/foo2/mylib.py") moobar()
  3. 運行文件:

     el@apollo:/home/el/foo$ python main.py hi

    moobar 函數是從 mylib.py 導入的,並在 main.py 中可用

示例 3,使用 from ... import ... 功能:

  1. 把它放在 /home/el/foo3/chekov.py 中:

     def question(): print "where are the nuclear wessels?"
  2. 把它放在 /home/el/foo3/main.py 中:

     from chekov import question question()
  3. 像這樣運行它:

     el@apollo:/home/el/foo3$ python main.py where are the nuclear wessels?

    如果您在 chekov.py 中定義了其他函數,除非您import * ,否則它們將不可用

示例 4,如果 riaa.py 與導入位置不同,則導入 riaa.py

  1. 把它放在 /home/el/foo4/stuff/riaa.py 中:

     def watchout(): print "computers are transforming into a noose and a yoke for humans"
  2. 把它放在 /home/el/foo4/main.py 中:

     import sys import os sys.path.append(os.path.abspath("/home/el/foo4/stuff")) from riaa import * watchout()
  3. 運行:

     el@apollo:/home/el/foo4$ python main.py computers are transforming into a noose and a yoke for humans

    這會從不同的目錄導入外部文件中的所有內容。

示例 5,使用os.system("python yourfile.py")

import os
os.system("python yourfile.py")

示例 6,通過搭載 python startuphook 導入文件:

更新:這個例子曾經適用於 python2 和 3,但現在只適用於 python2。 python3 擺脫了這個用戶啟動鈎子功能集,因為它被低技能的 Python 庫編寫者濫用,在所有用戶定義的程序之前使用它來不禮貌地將他們的代碼注入全局命名空間。 如果你想讓它適用於 python3,你將不得不變得更有創意。 如果我告訴你怎么做,python 開發人員也會禁用該功能集,所以你只能靠自己了。

請參閱: https ://docs.python.org/2/library/user.html

將此代碼放入您的主目錄~/.pythonrc.py

class secretclass:
    def secretmessage(cls, myarg):
        return myarg + " is if.. up in the sky, the sky"
    secretmessage = classmethod( secretmessage )

    def skycake(cls):
        return "cookie and sky pie people can't go up and "
    skycake = classmethod( skycake )

將此代碼放入您的 main.py 中(可以在任何地方):

import user
msg = "The only way skycake tates good" 
msg = user.secretclass.secretmessage(msg)
msg += user.secretclass.skycake()
print(msg + " have the sky pie! SKYCAKE!")

運行它,你應該得到這個:

$ python main.py
The only way skycake tates good is if.. up in the sky, 
the skycookie and sky pie people can't go up and  have the sky pie! 
SKYCAKE!

如果您在此處收到錯誤: ModuleNotFoundError: No module named 'user'那么這意味着您正在使用 python3,startuphooks 在默認情況下被禁用。

這個 jist 的功勞歸功於: https ://github.com/docwhat/homedir-examples/blob/master/python-commandline/.pythonrc.py 沿着你的船發送。

示例 7,最強大:使用裸導入命令在 python 中導入文件:

  1. 創建一個新目錄/home/el/foo5/
  2. 創建一個新目錄/home/el/foo5/herp
  3. 在 herp 下創建一個名為__init__.py的空文件:

     el@apollo:/home/el/foo5/herp$ touch __init__.py el@apollo:/home/el/foo5/herp$ ls __init__.py
  4. 創建一個新目錄 /home/el/foo5/herp/derp

  5. 在 derp 下,創建另一個__init__.py文件:

     el@apollo:/home/el/foo5/herp/derp$ touch __init__.py el@apollo:/home/el/foo5/herp/derp$ ls __init__.py
  6. 在 /home/el/foo5/herp/derp 下新建一個名為yolo.py的文件,把它放在那里:

     def skycake(): print "SkyCake evolves to stay just beyond the cognitive reach of " + "the bulk of men. SKYCAKE!!"
  7. 關鍵時刻,制作新文件/home/el/foo5/main.py ,把它放在那里;

     from herp.derp.yolo import skycake skycake()
  8. 運行:

     el@apollo:/home/el/foo5$ python main.py SkyCake evolves to stay just beyond the cognitive reach of the bulk of men. SKYCAKE!!

    空的__init__.py文件與 Python 解釋器通信,開發人員希望該目錄成為可導入的包。

如果您想查看我關於如何在目錄下包含所有 .py 文件的帖子,請參見此處: https ://stackoverflow.com/a/20753073/445131

importlib被添加到 Python 3 以編程方式導入模塊。

import importlib

moduleName = input('Enter module name:')
importlib.import_module(moduleName)

應該從moduleName中刪除 .py 擴展名。 該函數還為相對導入定義了一個package參數。

在 python 2.x 中:

  • 只需import file
  • 通過添加一個空的__init__.py文件,可以將文件夾標記為包
  • 您可以使用__import__函數,它將模塊名稱(不帶擴展名)作為字符串擴展名
pmName = input('Enter module name:')
pm = __import__(pmName)
print(dir(pm))

鍵入help(__import__)以獲取更多詳細信息。

第一個案例

您想在文件A.py中導入文件B.py ,這兩個文件在同一個文件夾中,如下所示:

. 
├── A.py 
└── B.py

您可以在文件B.py中執行此操作:

import A

或者

from A import *

或者

from A import THINGS_YOU_WANT_TO_IMPORT_IN_A

然后你就可以在文件A.py中使用文件B.py的所有功能了


第二種情況

您要在文件 B.py 中導入文件folder/A.py B.py這兩個文件不在同一個文件夾中,如下所示:

.
├── B.py
└── folder
     └── A.py

您可以在文件B.py中執行此操作:

import folder.A

或者

from folder.A import *

或者

from folder.A import THINGS_YOU_WANT_TO_IMPORT_IN_A

然后你就可以在文件A.py中使用文件B.py的所有功能了


概括

  • 在第一種情況下,文件A.py是您在文件B.py中導入的模塊,您使用了語法import module_name
  • 第二種情況下folder是包含模塊A.py的包,您使用了語法import package_name.module_name

有關包和模塊的更多信息,請參閱此鏈接

要在“運行時”導入具有已知名稱的特定 Python 文件:

import os
import sys

...

scriptpath = "../Test/"

# Add the directory containing your module to the Python path (wants absolute paths)
sys.path.append(os.path.abspath(scriptpath))

# Do the import
import MyModule

您沒有很多復雜的方法可以將 python 文件從一個文件夾導入到另一個文件夾。 只需創建一個__init__.py文件來聲明此文件夾是一個 python 包,然后轉到您要導入的主機文件,只需鍵入

from root.parent.folder.file import variable, class, whatever

導入文檔 .. -- 參考鏈接

需要__init__.py文件才能使 Python 將目錄視為包含包,這樣做是為了防止具有通用名稱(例如字符串)的目錄無意中隱藏模塊搜索路徑中稍后出現的有效模塊。

__init__.py可以只是一個空文件,但它也可以執行包的初始化代碼或設置__all__變量。

mydir/spam/__init__.py
mydir/spam/module.py
import spam.module
or
from spam import module
from file import function_name  ######## Importing specific function
function_name()                 ######## Calling function

import file              ######## Importing whole package
file.function1_name()    ######## Calling function
file.function2_name()    ######## Calling function

這是我現在理解的兩種簡單方法,並確保要作為庫導入的“file.py”文件僅存在於當前目錄中。

如果定義的函數在文件x.py

def greet():
    print('Hello! How are you?')

在要導入函數的文件中,寫下:

from x import greet

如果您不想導入文件中的所有函數,這很有用。

導入 .py 文件的最佳方式是通過__init__.py 最簡單的做法是在 your.py 文件所在的同一目錄中創建一個名為__init__.py的空文件。

Mike Grouchy 的這篇文章很好地解釋了__init__.py及其用於制作、導入和設置 python 包的用途。

我想在別處添加我不太清楚的注釋; 在模塊/包中,從文件加載時,模塊/包名稱必須以mymodule為前綴。 想象一下mymodule的布局是這樣的:

/main.py
/mymodule
    /__init__.py
    /somefile.py
    /otherstuff.py

__init__.py加載somefile.py / otherstuff.py時,內容應如下所示:

from mymodule.somefile import somefunc
from mymodule.otherstuff import otherfunc

使用 Python 3.5 或更高版本,您可以使用importlib.util直接將任意位置的.py文件作為模塊導入,而無需修改sys.path

import importlib.util
import sys

def load_module(file_name, module_name)
    spec = importlib.util.spec_from_file_location(module_name, file_name)
    module = importlib.util.module_from_spec(spec)
    sys.modules[module_name] = module
    spec.loader.exec_module(module)
    return module

file_name參數必須是字符串或類似路徑的對象。 module_name參數是必需的,因為所有加載的 Python 模塊都必須有一個(帶點的)模塊名稱(如sysimportlibimportlib.util ),但您可以為這個新模塊選擇任何可用的名稱。

你可以像這樣使用這個函數:

my_module = load_module("file.py", "mymod")

在使用load_module()函數將其導入 Python 進程一次后,該模塊將可以使用給定的模塊名稱導入。

# file.py =
print(f"{__name__} imported (file.py)")
# =========

# one.py ==
print(f"{__name__} imported (one.py)")
load_module("file.py", "mymod")
import two
# =========

# two.py ==
print(f"{__name__} imported (two.py)")
import mymod
# =========

鑒於上述文件,您可以運行以下命令來查看file.py是如何變得可導入的。

$ python3 -m one
__main__ imported (one.py)
two imported (two.py)
mymod imported (file.py)

此答案基於官方 Python 文檔: importlib : Importing a source file directly。

import sys
#print(sys.path)
sys.path.append('../input/tokenization')
import tokenization

要導入任何 .py 文件,您可以使用上面的代碼。

先追加路徑再導入

注意:'../input/tokenization'目錄包含tokenization.py文件

我如何導入是導入文件並使用它的名稱的簡寫。

import DoStuff.py as DS
DS.main()

不要忘記您的導入文件必須以 .py 擴展名命名

有幾種方法可以包含名稱為 abc.py 的 python 腳本

  1. 例如,如果您的文件被稱為 abc.py (import abc) 限制是您的文件應該出現在您的調用 python 腳本所在的同一位置。

導入 abc

  1. 例如,如果您的 python 文件位於 Windows 文件夾中。 Windows 文件夾位於調用 python 腳本的同一位置。

從文件夾導入 abc

  1. Incase abc.py 腳本在文件夾內部的 internal_folder 中可用

從文件夾.internal_folder 導入 abc

  1. 正如上面詹姆斯所回答的那樣,如果您的文件位於某個固定位置

導入操作系統
導入系統
腳本路徑 = "../Test/MyModule.py"
sys.path.append(os.path.abspath(scriptpath))
導入我的模塊

如果您的 python 腳本得到更新並且您不想上傳 - 使用這些語句進行自動刷新。 獎金 :)

%load_ext autoreload 
%autoreload 2

如果您要導入的模塊不在子目錄中,請嘗試以下操作並從最深的公共父目錄運行app.py

目錄結構:

/path/to/common_dir/module/file.py
/path/to/common_dir/application/app.py
/path/to/common_dir/application/subpath/config.json

app.py中,將客戶端的路徑附加到 sys.path:

import os, sys, inspect

sys.path.append(os.getcwd())
from module.file import MyClass
instance = MyClass()

可選(如果您加載例如配置)(檢查似乎是我的用例中最強大的)

# Get dirname from inspect module
filename = inspect.getframeinfo(inspect.currentframe()).filename
dirname = os.path.dirname(os.path.abspath(filename))
MY_CONFIG = os.path.join(dirname, "subpath/config.json")

user@host:/path/to/common_dir$ python3 application/app.py

該解決方案在 cli 和 PyCharm 中都適用於我。

這就是我從 python 文件中調用函數的方式,這對我來說可以靈活地調用任何函數。

import os, importlib, sys

def callfunc(myfile, myfunc, *args):
    pathname, filename = os.path.split(myfile)
    sys.path.append(os.path.abspath(pathname))
    modname = os.path.splitext(filename)[0]
    mymod = importlib.import_module(modname)
    result = getattr(mymod, myfunc)(*args)
    return result

result = callfunc("pathto/myfile.py", "myfunc", arg1, arg2)

只是將python文件導入另一個python文件

假設我有helper.py python 文件,它具有顯示功能,例如,

def display():
    print("I'm working sundar gsv")

現在在app.py中,你可以使用顯示功能,

import helper
helper.display()

輸出,

I'm working sundar gsv

注意:無需指定 .py 擴展名。

你也可以這樣做: from filename import something

示例: from client import Client請注意,您不需要.py .pyw .pyui擴展名。

這聽起來可能很瘋狂,但如果您只是為其創建一個包裝腳本,則可以創建一個指向要導入的文件的符號鏈接。

Python 的一個非常不為人知的特性是能夠導入zip文件:

library.zip
|-library
|--__init__.py

包的__init__.py文件包含以下內容:

def dummy():
    print 'Testing things out...'

我們可以編寫另一個腳本,它可以從 zip 存檔中導入一個包。 只需將 zip 文件添加到 sys.path。

import sys
sys.path.append(r'library.zip')

import library

def run():
    library.dummy()

run()

這有助於我使用Visual Studio Code構建我的 Python 項目。

當您沒有在目錄中聲明__init__.py時,可能會導致問題。 並且該目錄成為implicit namespace package 這是關於Python 導入和項目結構的一個很好的總結。

此外,如果您想使用 Visual Studio Code 運行按鈕運行按鈕 在帶有不在主包內的腳本的頂部欄中,您可以嘗試從實際目錄運行控制台。

例如,您想從測試包中執行一個打開的test_game_item.py ,並且您在omission (主包)目錄中打開了 Visual Studio Code:

├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore

目錄結構來自[ 2 ]。

您可以嘗試設置:

(Windows) Ctrl + Shift + P首選項:打開設置 (JSON)

將此行添加到您的用戶設置

"python.terminal.executeInFileDir": true

其他系統的更全面的答案也在這個問題中。

方法有很多,如上所列,但我發現我只想導入一個文件的內容,不想寫一行行又非要導入其他模塊。 因此,我想出了一種獲取文件內容的方法,即使使用點語法( file.property ),而不是將導入的文件與您的文件合並。
首先,這是我要導入的文件data.py

    testString= "A string literal to import and test with"


注意:您可以改用.txt擴展名。
mainfile.py中,首先打開並獲取內容。

    #!usr/bin/env python3
    Data=open('data.txt','r+').read()

現在您將內容作為字符串,但嘗試訪問data.testString會導致錯誤,因為datastr類的實例,即使它確實具有屬性testString它也不會達到您的預期。
接下來,創建一個類。 例如(雙關語), ImportedFile

    class ImportedFile:

並將其放入其中(帶有適當的縮進):

    exec(data)


最后,像這樣重新分配data

    data=ImportedFile()

就是這樣! 就像訪問任何其他模塊一樣,鍵入print(data.testString)將打印到控制台A string literal to import and test with
但是,如果您想要from mod import *的等價物,只需刪除類、實例分配並刪除exec即可。

希望這可以幫助:)
-本吉

from y import * 
  • 假設您有一個文件 x 和 y。
  • 您想將 y 文件導入 x。

然后轉到您的 x 文件並放置上述命令。 要測試這一點,只需在您的 y 文件中放置一個打印功能,當您的導入成功時,它應該在 x 文件中打印它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM