Python:在个人Python包中包含第三方库

umb*_*987 4 python path environment-variables pythonpath python-2.7

我想在我的Python脚本文件夹中包含一个第三方库,以将其全部分发(我不知道发行许可证,可以很好地分发该库)。这是为了避免将库安装在另一台机器上。

说我有一个脚本(my_script.py),它将调用此外部库。我试图将此库从Python目录的site-packages子目录复制到我有文件的目录中,但这似乎还不够(我认为原因是__init__.py该库的中,可能需要将文件夹放在其中的PYTHONPATH)。

为了使所有内容正常工作my_script.pysys.path在其中插入一些代码行以将其文件夹临时附加到其中是否合理?

例如,如果我有一个类似于以下的结构:

Main_folder
my_script.py
  /external_lib_folder
   __init__.py
   external_lib.py
Run Code Online (Sandbox Code Playgroud)

并且external_lib_folder是我从site-packages复制的外部库并将其插入到我的库中Main_folder,如果我将这些行(例如)写在中会很好my_script.py吗?

import os,sys
main_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(main_dir)
Run Code Online (Sandbox Code Playgroud)

编辑

我最终选择了sys.path.append解决方案。我将这些行添加到我的my_script.py

import os, sys

# temporarily appends the folder containing this file into sys.path
main_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),'functions')
sys.path.append(main_dir)
Run Code Online (Sandbox Code Playgroud)

无论如何,由于他花了很多时间帮助我(当然,因为他的解决方案也行得通),所以我选择将其作为问题的编辑内容并接受Torxed的答案。

Tor*_*xed 5

Python3

import importlib.machinery, imp
namespace = 'external_lib'
loader = importlib.machinery.SourceFileLoader(namespace, '/home/user/external_lib_folder/external_lib.py')
external_lib = loader.load_module(namespace)

# How to use it:
external_lib.function(data_or_something)
Run Code Online (Sandbox Code Playgroud)

这将是在Python 3中加载自定义路径的理想方法。
不能完全确定这是您想要的,但它的相关性足以发布添加到的替代方法sys.path

Python2

在python 2中,您可以做(如果我没记错的话,有一段时间了,因为我使用了旧版本的Python):

external_lib = __import__('external_lib_folder')
Run Code Online (Sandbox Code Playgroud)

但是,这确实需要您__init__.py在悲伤的脚本中保留和正确的函数声明,否则它将失败。
**同样重要的是,您要导入的文件夹的名称与__init__.pysad文件夹中的脚本试图导入的子文件夹的名称相同,例如geopy

./myscript.py
./geopy/
./geopy/__init__.py
./geopy/compat.py
...
Run Code Online (Sandbox Code Playgroud)

的代码myscript.py如下所示:

handle = __import__('geopy')
print(handle)
Run Code Online (Sandbox Code Playgroud)

这将产生以下输出:

[user@machine project]$ python2 myscript.py 
<module 'geopy' from '/home/user/project/geopy/__init__.pyc'>

[user@machine project]$ tree -L 2
.
??? geopy
?   ??? compat.py
?   ??? compat.pyc
?   ??? distance.py
?   ??? distance.pyc
?   ??? exc.py
?   ??? exc.pyc
?   ??? format.py
?   ??? format.pyc
?   ??? geocoders
?   ??? __init__.py
?   ??? __init__.pyc
?   ??? location.py
?   ??? location.pyc
?   ??? point.py
?   ??? point.pyc
?   ??? units.py
?   ??? units.pyc
?   ??? util.py
?   ??? util.pyc
?   ??? version.pyc
??? myscript.py

2 directories, 20 files
Run Code Online (Sandbox Code Playgroud)

因为在__init__.pygeopy,它定义了导入,例如from geopy.point import Point需要存在名称空间或文件夹的导入geopy
在那里,您无法将文件夹重命名functionsgeopy在其中放置名为的文件夹,因为那样将无法正常工作,也无法将geopy文件夹中的内容放置在称为的文件夹中,functions因为这不是您想要geopy的。

将路径添加到sys.path(Py2 + 3)

如注释中所述,您还可以在sys.path导入之前将文件夹添加到变量中。

import sys
sys.path.insert(0, './functions')

import geopy
print(geopy)

>>> <module 'geopy' from './functions/geopy/__init__.pyc'>
Run Code Online (Sandbox Code Playgroud)

为什么这是一个坏主意:它将起作用,并且被许多人使用。可能出现的问题是,如果您不小心从中导入内容,则可能会替换系统功能或从其他文件夹加载其他模块。该应用程序可.insert(0, ...)用于大多数应用程序,并确保您确实有冒险将系统内置程序替换为“不完整的”路径名。