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

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

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

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

Main_folder
my_script.py
  /external_lib_folder
   __init__.py
   external_lib.py

并且external_lib_folder是我从网站程序包中复制并插入到Main_folder中的外部库,如果我将这些行(例如)写在my_script.py中会好吗?
import os,sys
main_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(main_dir)

编辑

我最终选择了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)

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

最佳答案

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)

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

Python2

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

但是,这确实需要您在悲伤的脚本中保留__init__.py和正确的函数声明,否则它将失败。
**同样重要的是,您要导入的文件夹的名称与sad文件夹中__init__.py脚本试图从其导入子库的名称相同,例如geopy将为:
./myscript.py
./geopy/
./geopy/__init__.py
./geopy/compat.py
...
myscript.py的代码如下所示:
handle = __import__('geopy')
print(handle)

这将产生以下输出:
[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

因为在__init__.pygeopy中,它定义了导入,例如from geopy.point import Point,它需要存在 namespace 或geopy文件夹。
在那里,您无法将文件夹重命名为functions并在其中放置名为geopy的文件夹,因为那样将无法工作,也无法将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'>

为什么这是个坏主意:它可以工作,并且被许多人使用。可能出现的问题是,如果您不小心从中导入内容,则可能会替换系统功能,或者其他模块可能会从其他文件夹加载。大多数情况下都可以使用.insert(0, ...),并确保您确实有冒着用“不透明”路径名替换系统内置组件的风险。

关于Python:在个人Python包中包含第三方库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35849429/

10-12 18:44