【问题标题】:How to import other Python files?如何导入其他 Python 文件?
【发布时间】:2021-10-04 16:12:06
【问题描述】:

如何在 Python 中导入其他文件?

  1. 如何准确导入特定的 python 文件,如 import file.py
  2. 如何导入文件夹而不是特定文件?
  3. 我想在运行时根据用户动态加载 Python 文件 输入。
  4. 我想知道如何只加载文件中的一个特定部分。

例如,在main.py 我有:

from extra import * 

虽然这给了我extra.py 中的所有定义,但也许我想要的只是一个定义:

def gap():
    print
    print

我要在import 语句中添加什么才能从extra.py 获得gap

【问题讨论】:

  • 如果 A 和 B 是同一目录下的两个文件,在 python 3.x 中,并且您要导入 A 的内容,import A 将不起作用。我们必须使用 from current_directory_name import *from current_directory_name import THINGS_YOU_WANT_TO_IMPORT 。玩一下从不同目录导入

标签: python python-import python-module python-packaging


【解决方案1】:

导入 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 或 (exec in Python 3) 来执行其他 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,默认情况下启动挂钩在此处禁用。

此 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

【讨论】:

  • 您还应该添加示例 6:使用 __import__(py_file_name)。无论如何,很棒的指南
  • 每次我遇到导入问题时,我都会遇到这个问题,并且总能解决我的问题。如果每次你帮助我时我都能对此表示赞同,我会的。
  • 所有这些之间的最大区别是什么,为什么一个比其他任何一个都好?例如5,你写了“在python中使用bare import命令导入文件”,但是你在例子1、3和4中也使用了(bare?)import命令,不是吗?
  • 很好的答案,但您总是使用不同的导入文件作为示例,这使得阅读起来很麻烦。
  • 我想强调的是,即使您在 Windows 上工作,导入也是区分大小写的。所以你不能有 Module.py 并且在你的代码中有 import module
【解决方案2】:

importlib 被添加到 Python 3 以通过编程方式导入模块。

import importlib

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

应该从moduleName 中删除 .py 扩展名。该函数还为相对导入定义了一个package 参数。

在 python 2.x 中:

  • 只需 import file 不带 .py 扩展名
  • 可以通过添加一个空的__init__.py 文件将文件夹标记为包
  • 可以使用__import__函数,将模块名(不带扩展名)作为字符串扩展名
pmName = input('Enter module name:')
pm = __import__(pmName)
print(dir(pm))

输入help(__import__)了解更多详情。

【讨论】:

  • 如果在 init.py 中添加import filename,则可以直接将模块作为文件夹名称导入。
  • 来自help(__import__):Because this function is meant for use by the Python interpreter and not for general use it is better to use importlib.import_module() to programmatically import a module.
  • 如果不是包而是脚本文件怎么办?
  • 2019年还准确吗?是python3还是2?
  • 在 Python 中导入是一个奇怪的混乱。应该可以从任何文件中导入任何函数,只需一行简单的代码即可提供文件的路径(绝对或相对、硬编码或存储在变量中)。 Python,去做吧!
【解决方案3】:

在“运行时”导入具有已知名称的特定 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

【讨论】:

  • 我的朋友今天检查了这个,没有运气 - 看起来文件名不应该在那里。他使用了父目录中的本地文件,“./”最后就像父目录(..)一样工作。修复帖子中的问题被拒绝 - 可能是误解(?)如果您不确定,请打印 sys.path 并比较记录...
【解决方案4】:

第一种情况

你想在文件B.py中导入文件A.py,这两个文件在同一个文件夹中,像这样:

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

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

import A

from A import *

from A import THINGS_YOU_WANT_TO_IMPORT_IN_A

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


第二种情况

你想在文件B.py中导入文件folder/A.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

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


总结

  • 第一种情况中,文件A.py 是您在文件B.py 中导入的模块,您使用了语法import module_name
  • 第二种情况中,folder 是包含模块A.py 的包,您使用了语法import package_name.module_name

有关包和模块的更多信息,请参阅link

【讨论】:

  • 我尝试了一些变化,它奏效了。 from folder_a.script import * Script.py 在文件夹 a 下。
  • +1 这就是我要找的。无法理解其他答案,但您使用目录进行了解释。
  • @bytedev 将import syssys.path.append("..") 添加到文件的开头。据此:stackoverflow.com/a/48341902/6057480。经测试,完美运行,完成后,可以在父目录下导入py文件,在同目录和子目录下仍然可以导入py文件。
  • 那对你来说很酷,兄弟,我在 3.8.x 中,但它对我不起作用。
  • 我在windows 8.1;我正在使用 python-3.8.5-embed-amd64。但它不起作用。
【解决方案5】:

您没有很多复杂的方法可以将 python 文件从一个文件夹导入到另一个文件夹。只需创建一个 __init__.py 文件来声明此文件夹是一个 python 包,然后转到您要导入的主机文件,只需键入

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

【讨论】:

  • 如果我想要一个相对路径怎么办?
【解决方案6】:

Import doc .. -- 参考链接

__init__.py 文件是 Python 将目录视为包含包所必需的,这样做是为了防止具有通用名称(例如字符串)的目录无意中隐藏模块搜索路径中稍后出现的有效模块。

__init__.py 可以只是一个空文件,但它也可以执行包的初始化代码或设置__all__ 变量。

mydir/spam/__init__.py
mydir/spam/module.py
import spam.module
or
from spam import module

【讨论】:

    【解决方案7】:
    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”文件仅存在于当前目录中。

    【讨论】:

      【解决方案8】:

      如果定义的函数在文件x.py中:

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

      在要导入函数的文件中,写下:

      from x import greet
      

      如果您不想导入文件中的所有函数,这很有用。

      【讨论】:

        【解决方案9】:

        我的导入方式是导入文件并使用其名称的简写。

        import DoStuff.py as DS
        DS.main()
        

        不要忘记您的导入文件必须以 .py 扩展名命名

        【讨论】:

        • 不会import DoStuff.py as DS 尝试从DoStuff 导入py
        • 这是一个交易破坏者。在极端情况下,我现在将嵌入 PHP 来导入,我真的不需要只导入 def。我可能想导入“仅限开发”的小册子或常见的 app.cfg 文件。我只想能够替换代码。对其进行预处理是一种糟糕的方式。
        【解决方案10】:

        导入 .py 文件的最佳方式是通过__init__.py。最简单的做法是在 your.py 文件所在的同一目录中创建一个名为 __init__.py 的空文件。

        Mike Grouchy 的这个post 很好地解释了__init__.py 及其用于制作、导入和设置python 包的用途。

        【讨论】:

        【解决方案11】:

        我想添加这个我在其他地方不太清楚的注释;在模块/包中,从文件加载时,模块/包名称必须以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
        

        【讨论】:

          【解决方案12】:
          import sys
          #print(sys.path)
          sys.path.append('../input/tokenization')
          import tokenization
          

          要导入任何 .py 文件,您可以使用上述代码。

          先追加路径再导入

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

          【讨论】:

            【解决方案13】:

            有几种方法可以将你的 python 脚本包含在 abc.py 中

            1. 例如如果您的文件名为 abc.py (import abc) 限制是您的文件应该与调用 python 脚本的位置相同。

            导入 abc

            1. 例如如果您的 python 文件位于 Windows 文件夹中。 Windows 文件夹位于调用 python 脚本的同一位置。

            从文件夹导入 abc

            1. Incase abc.py 脚本在文件夹内部的 internal_folder 中可用

            从文件夹.internal_folder 导入 abc

            1. 正如上面 James 的回答,如果您的文件位于某个固定位置

            导入操作系统
            导入系统
            脚本路径 = "../Test/MyModule.py"
            sys.path.append(os.path.abspath(scriptpath))
            导入我的模块

            如果您的 python 脚本被更新并且您不想上传 - 使用这些语句进行自动刷新。奖金:)

            %load_ext autoreload 
            %autoreload 2
            

            【讨论】:

              【解决方案14】:

              使用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.

              【讨论】:

                【解决方案15】:

                如果您要导入的模块不在子目录中,请尝试以下操作并从最深的公共父目录运行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 中都适用于我。

                【讨论】:

                  【解决方案16】:

                  这就是我从 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)
                  

                  【讨论】:

                  • 制作一个新函数比直接使用函数有什么好处?
                  • @qwr 新函数 callfunc() 只是代码的包装器,用于动态调用 python 文件中的目标函数。给出的示例是 python 文件“pathto/myfile.py”中的目标“myfunc”。 “直接使用函数”是什么意思?
                  • 非常适合我。在我的示例中,我将:from mypath import Path 替换为 Path = callfunc("/folder/to/mypath.py", "Path")。谢谢@Xiao-FengLi
                  【解决方案17】:

                  只是在另一个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 扩展名。

                  【讨论】:

                    【解决方案18】:

                    这听起来可能很疯狂,但如果您只是为要导入的文件创建一个包装脚本,则可以创建一个符号链接。

                    【讨论】:

                      【解决方案19】:

                      您也可以这样做:from filename import something

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

                      【讨论】:

                        【解决方案20】:

                        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()
                        

                        【讨论】:

                          【解决方案21】:

                          方法有很多,如上所列,但我发现我只想导入文件的内容,不想写行又要导入其他模块。因此,我想出了一种获取文件内容的方法,即使使用点语法 (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

                          希望这会有所帮助:)
                          -本吉

                          【讨论】:

                          • 当我们拥有人们发布的所有其他解决方案时,您真的认为将文件内容作为字符串读取然后执行它是一个很好的解决方案吗?
                          • @qwr 嗯,是的,我愿意。许多其他答案在某些情况下不起作用。这就是为什么我需要一种保证工作的简单方法。如果你无法从别人的角度看事物,你需要尝试使用官方的 IDLE。
                          【解决方案22】:
                          from y import * 
                          
                          • 假设您有一个文件 x 和 y。
                          • 您想将 y 文件导入 x。

                          然后转到您的 x 文件并放置上述命令。要对此进行测试,只需在您的 y 文件中放置一个打印功能,当您的导入成功时,它应该在 x 文件中打印它。

                          【讨论】:

                            猜你喜欢
                            • 2022-01-22
                            • 2012-10-07
                            • 1970-01-01
                            • 2019-10-24
                            相关资源
                            最近更新 更多