Python: 在个人 Python 包中包含第三方库
Python: include a third party library in a personal Python package
我想在我的 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.
中加载自定义路径的理想方式
不完全确定这是你想要的,但它足够相关 post 作为添加到 sys.path
.
的替代方法
Python2
在 python 2 中你可以这样做(如果我没记错的话,自从我使用旧版本的 Python 以来已经有一段时间了):
external_lib = __import__('external_lib_folder')
然而,这确实需要您在 sad 脚本中保留 __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
因为在 geopy
的 __init__.py
中,它定义了诸如 from geopy.point import Point
之类的导入,它需要存在 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, ...)
并确保您确实想要冒险用 "shady" 路径名替换系统内置函数。
你的建议是不好的做法,是一个弱安排。最好的解决方案(也很容易做到)是正确打包并添加显式依赖项,如下所示:
从设置工具导入设置
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)。
我想在我的 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.
中加载自定义路径的理想方式
不完全确定这是你想要的,但它足够相关 post 作为添加到 sys.path
.
Python2
在 python 2 中你可以这样做(如果我没记错的话,自从我使用旧版本的 Python 以来已经有一段时间了):
external_lib = __import__('external_lib_folder')
然而,这确实需要您在 sad 脚本中保留 __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
因为在 geopy
的 __init__.py
中,它定义了诸如 from geopy.point import Point
之类的导入,它需要存在 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, ...)
并确保您确实想要冒险用 "shady" 路径名替换系统内置函数。
你的建议是不好的做法,是一个弱安排。最好的解决方案(也很容易做到)是正确打包并添加显式依赖项,如下所示:
从设置工具导入设置
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)。