我想在我的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的答案,因为他花了很多时间帮助我(当然因为他的解决方案也有效)。
答案 0 :(得分:5)
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
的替代方案。
在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__.py
的{{1}}中,它定义了geopy
等导入需要名称空间或from geopy.point import Point
文件夹的导入。 />
在那里,您无法将文件夹重命名为geopy
,并在其中放置一个名为functions
的文件夹,因为它不会起作用,也不会将geopy
的内容放入其中一个名为geopy
的文件夹,因为它不是functions
所寻找的内容。
geopy
(Py2 + 3)如评论中所述,您还可以在导入之前将文件夹添加到sys.path
变量。
sys.path
为什么这是一个坏主意:它会起作用,并被许多人使用。可能出现的问题是,可能替换系统功能,或者如果您不小心从哪里导入内容,可能会从其他文件夹加载其他模块。大多数情况下都可以使用import sys
sys.path.insert(0, './functions')
import geopy
print(geopy)
>>> <module 'geopy' from './functions/geopy/__init__.pyc'>
,并确保您确实希望冒险使用&#34; shady&#34;替换系统内置插件。路径名称。
答案 1 :(得分:1)
你的建议是不好的做法,这是一种薄弱的安排。最好的解决方案(这也很容易)是正确打包并添加显式依赖,如下所示:
来自setuptools导入设置
setup(name='funniest',
version='0.1',
description='The funniest joke in the world',
url='http://github.com/storborg/funniest',
author='Flying Circus',
author_email='flyingcircus@example.com',
license='MIT',
packages=['funniest'],
install_requires=[
'markdown',
],
zip_safe=False)
如果第三方库处于pipy状态,这将有效。如果不是,请使用:
setup(
...
dependency_links=['http://github.com/user/repo/tarball/master#egg=package-1.0']
...
)
(有关包装,请参阅this explanation。)