[Python 세 가지 패키징 방법] 프로젝트 패키징을 구현하기 위해 PyInstaller 및 setupTools 및 복사 환경 사용
기사 디렉토리
1. setupTools와 PyInstaller 패키징의 차이점
pyinstaller
포장 과 의 setuptools
차이점은 무엇입니까 ?ChatGPT
pyinstaller
와setuptools
둘 다Python
에서 이지만 주요 목적과 작업 방식이 약간 다릅니다.
pyinstaller
코드를 실행 파일로 패키징Python
할 수 있는 도구로 , 코드 해석기 없이 코드를 실행할 수 있습니다 . 이를 통해 Python이 설치되지 않은 사용자에게 Python 애플리케이션을 배포하거나 Python 환경이 없는 시스템에 배치 할 수 있습니다 .Python
Python
setuptools
PyPI 또는 다른 패키지 관리자에 게시할 수 있는 설치 가능한 패키지로 코드를 패키징하는 데 도움이 되는Python
패키지 빌드 . 패키지 메타데이터, 종속성 및 기타 설정을 정의하기 위한 많은 옵션과 패키지 패키징을 위한 명령줄 도구도 있습니다.Python
setuptools
pyinstaller
따라서setuptools
둘 다 Python 코드를 독립형 배포판으로 패키징할 수 있지만 주요 목적은 약간 다릅니다.
Python
응용 프로그램을 단일 실행 파일로 패키징하려는 경우 선택 사항입니다pyinstaller
.
Python
코드를 설치 가능한 패키지 로 패키징 하고PyPI
다른 경우 선택 사항입니다setuptools
.
2. setupTools를 사용하여 로컬 프로젝트 패키징
참고
0) 프로젝트 준비 및 생성 requirements.txt
및 패키지 파일 작성
가) 프로젝트 준비
Python 프로젝트의 디렉터리 구조가 다음과 같다고 가정합니다.
여기서 pdf_handler.py
코드는 다음과 같습니다.
import pdfplumber
from PyPDF2 import PdfReader, PdfWriter
import os
import sys
pdf_path = "resume.pdf" #相对位置,不能使用绝对位置
#提取PDF文字
def extract_pdf_text():
# 提取pdf指定页的文字
with pdfplumber.open(pdf_path) as pdf:
page01 = pdf.pages[0] # 指定页码
text = page01.extract_text() # 提取文本
print(f"第一页pdf的文本内容为:{
text}",end='\n')
#提取所有页pdf文字
with pdfplumber.open(pdf_path) as pdf:
print(f"所有页pdf的文本内容如下:")
for page in pdf.pages: #遍历所有页
text = page.extract_text() # 提取当前页的文本
print(text)
#提取PDF表格
def extract_pdf_table():
with pdfplumber.open(pdf_path) as pdf:
print(f"所有页pdf的表格内容如下:")
for page in pdf.pages: # 遍历所有页
table = page.extract_table() # 提取当前页的文本
print(table)
#分割PDF
def split_pdf():
#如果使用PdfFileReader会抛出异常:PyPDF2.errors.DeprecationError: PdfFileReader is deprecated and was removed in PyPDF2 3.0.0. Use PdfReader instead.
file_reader = PdfReader(pdf_path) #实例化pdf reader对象
# getNumPages() 获取总页数会报错:PyPDF2.errors.DeprecationError: reader.getNumPages is deprecated and was removed in PyPDF2 3.0.0. Use len(reader.pages) instead.
for page in range(len(file_reader.pages)):
file_writer = PdfWriter() #实例化pdf writer对象
# 将遍历的每一页对象添加到pdf writer对象中,使用file_reader.getPage(page)会报错:PyPDF2.errors.DeprecationError: reader.getPage(pageNumber) is deprecated and was removed in PyPDF2 3.0.0. Use reader.pages[page_number] instead.
file_writer.add_page(file_reader.pages[page]) #PyPDF2.errors.DeprecationError: addPage is deprecated and was removed in PyPDF2 3.0.0. Use add_page instead.
with open(f'{
os.path.join(saveDir,str(page)+".pdf")}', 'wb') as out:
file_writer.write(out)
그중 main.py
주요 기능 항목인 코드는 다음과 같습니다.
from pdf_task.pdf_handler import extract_pdf_text,extract_pdf_table,split_pdf
import os
if __name__ == '__main__':
print("Hello world")
extract_pdf_text()
extract_pdf_table()
split_pdf()
os.system("pause")
여기에 두 개의 동일한 모듈을 만들어 패키지에 이 두 모듈을 포함시키는 pdf_task
것을 시뮬레이트합니다 .pypi_test
b) 생성requirements.txt
그런 다음 프로젝트의 루트 디렉터리에서 pypi_test
()를 사용하여 전체 패키지에 대한 타사 종속성 파일을 생성pipreqs
합니다 . ( 파이썬에서 requirements.txt를 생성하는 두 가지 방법 참조 )requirements.txt
pip install pipreqs -i https://pypi.tuna.tsinghua.edu.cn/simple
#生成requirements.txt命令如下
pipreqs . --encoding=utf8 --force #如果requirement.txt已存在,则
requirement.txt
생성된 콘텐츠는 다음과 같습니다.
pdfplumber==0.8.0
PyPDF2==3.0.1
setuptools==67.3.3
c) 패키지 파일 작성
그런 다음 해당 패키지 파일을 만들고 작성합니다 .
-
README.md
: 이 항목에 대한 구체적인 설명(맞춤형) -
LICENSE
https://choosealicense.com/
: 프로젝트 소유권 및 사용 제약(커스텀, 참조 ) 등의 문제에 대한 설명 -
pyproject.toml
:setuptools
지정해야 하는 최소 버전, 스크립트 내용은 다음과 같습니다.[build-system] requires = ["setuptools>=42"] build-backend = "setuptools.build_meta"
-
setup.py
setuptools
: 패키징 스크립트 사용 내용은 다음과 같은 부분이 포함되어 있습니다 참조 Python 프로젝트 코드 작성 후 패키징 및 릴리스는 어떻게 하나요?name: 你定义的包名,可以用字母、数字、下划线,需要确保唯一性。 version: 项目的版本号。 author: 你(作者)的名称。 author_email: 你(作者) 的邮箱。 description: 项目的简要描述。 long_description_content_type:长描述内容的使用的标记类型,一般为 markdown 或者 rst。 url: 你这个项目的主页地址,也可以直接链接到你这个项目的Github 地址上面去。 include_package_data: 是否添加 py 以外的文件。 package_data: 需要添加 Python 的额外文件列表。 packages: 直接用 setuptool 找到你项目所有相关的包列表。这里直接使用find_packages()自动寻找 classifiers: 附加说明,比如这里写的就是使用于 Python3 版本,使用的是 MIT 协议,独立于 OS。 python_requires: python 版本要求。
제가 작성한 스크립트는
setup.py
다음과 같습니다.#参考 https://juejin.cn/post/7053009657371033630, https://zhuanlan.zhihu.com/p/527321393 #!/usr/bin/env python from os import path from setuptools import setup, find_packages here = path.abspath(path.dirname(__file__)) with open(path.join(here, 'requirements.txt'), 'r', encoding='utf-8') as f: all_reqs = f.read().split('\n') with open(path.join(here, 'README.md'), 'r', encoding='utf-8') as f: long_description = f.read() install_requires = [x.strip() for x in all_reqs if 'git+' not in x] setup( name='pypi_test', # 必填,项目的名字,用户根据这个名字安装,pip install SpiderKeeper-new version='1.0.0', # 必填,项目的版本,建议遵循语义化版本规范 author='wangxiaoxi', # 项目的作者 description='pypi测试', # 项目的一个简短描述 long_description=long_description, # 项目的详细说明,通常读取 README.md 文件的内容 long_description_content_type='text/markdown', # 描述的格式,可选的值: text/plain, text/x-rst, and text/markdown author_email='[email protected]', # 作者的有效邮箱地址 url='https://github.com/test', # 项目的源码地址 license='MIT', include_package_data=True, package_data= { 'src' : ["resources/"] }, packages=find_packages(), # 必填,指定打包的目录,默认是当前目录,如果是其他目录比如 src, 可以使用 find_packages(where='src') install_requires=install_requires, # 指定你的项目依赖的 python 包,这里直接读取 requirements.txt # 分类器通过对项目进行分类,帮助用户找到项目 classifiers=[ 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 3', ], python_requires=">=3.8" )
위의 파일을 모두 작성한 후 디렉토리 구조는 다음과 같습니다.
1) 소스 및 바이너리 설치 가능 패키지( )로 패키징 whl
및 참조
-
먼저
setuptools
및 의 버전을 업그레이드하십시오wheel
.pip install --upgrade setuptools wheel
-
그런 다음 루트 디렉터리(
pypi_test
)에서 다음 명령을 사용하여 소스 코드를 패키징합니다.python setup.py sdist
이때 루트 디렉토리 아래에
dist
패키지된 소스 코드 압축 패키지가 들어 있는 폴더가 생성 되며pypi_test-1.0.0.tar.gz
, 압축 해제 후 루트 디렉토리 아래python
소스 코드가 됩니다 . -
그런 다음 루트 디렉터리(
pypi_test
)에서 다음 명령을 사용하여 소스 코드를 패키징합니다.python setup.py bdist_wheel
이때 해당
dist
폴더에는 해당 프로젝트의 바이너리 설치 가능 파일이 생성되며pypi_test-1.0.0-py3-none-any.whl
정적 리소스를 제외한 전체 프로젝트의 두 모듈의 소스 코드를 포함 하는 폴더build
가 생성됩니다lib
python
. -
소스 코드를 패키징하고 바이너리 설치 가능 소프트웨어 패키지를 동시에 패키징하려면 다음 명령을 직접 사용할 수 있습니다.
python setup.py sdist bdist_wheel
패키지된 디렉토리 구조는 다음과 같습니다.
이 패키지를 참조하려면 직접 pip install .\pypi_test-1.0.0-py3-none-any.whl
,
그런 다음 새 프로젝트에서 하나를 만들어 이 프로젝트 python_test
의 두 모듈을 직접 참조합니다 .pdf_task
pdf_task2
from pdf_task.pdf_handler import extract_pdf_text
extract_pdf_text()
# 或许会报找不到静态资源的错误:FileNotFoundError: [Errno 2] No such file or directory: 'D:\\programSoftware\\python\\anaconda\\envs\\spider_env\\lib\\site-packages\\pdf_task\\resume.pdf',
# 可以将resume.pdf放到"site-packages/pdf_task/'中即可解决
이 패키지를 사용하지 않으려면 pip uninstall pypi_test
로 제거할 수 있습니다. 여기서 는 에 구성된 프로젝트 이름 pypi_test
입니다setup.py
.
2) PyPI에 whl 업로드
먼저 https://pypi.org/account/register/pypi
에서 계정을 등록합니다 .
그런 다음 다음을 설치하십시오 twine
.
pip install twine
마지막으로 pypi_test
디렉터리 에서 setupTools
패키징된 dist
파일을 pypi
다음 위치에 업로드합니다.
twine upload dist/*
가능한 문제들:
오류 1 : 업로드된
dist
폴더에whl
다음 이외의 폴더가 포함되어 있습니다.(spider_env) PS D:\桌面\pypi_test> twine upload dist/* Uploading distributions to https://upload.pypi.org/legacy/ ERROR InvalidDistribution: Unknown distribution format: 'pypi_test-1.0.0'
해결 방법 :
dist
폴더에서 중복 폴더를 삭제합니다.오류 2 : 프로젝트 이름이 다른 사람에 의해 사용되었습니다. HTTPError: 403 클라이언트 오류: 사용자가 프로젝트에 업로드하도록 허용됨 · GitHub를 참조하십시오.
ERROR HTTPError: 403 Forbidden from https://upload.pypi.org/legacy/ The user 'wangxiaoxi' isn't allowed to upload to project 'pypi_test'. See https://pypi.org/help/#project-name for more information.
해결 방법 : 원본 파일을 삭제하고 프로젝트 이름을
whl
수정하여 다시 패키징한 후 다시 업로드합니다.setup.py
여기서 프로젝트 이름을wangwangwang_pypi_test
.
업로드에 성공하면 콘솔의 링크를 통해 액세스할 수 있습니다.
3) 가능한 문제
모듈 이름은 python
키워드가 될 수 없습니다(예: main
). 그렇지 않으면 패키징이 성공하더라도 직접 참조할 수 없습니다 .
3. PyInstaller를 사용하여 로컬 프로젝트 패키징
참고
1) PyInstaller는 주요 기능을 실행 파일로 패키징합니다.
pyinstaller
패키징 명령 의 매개변수는 다음과 같습니다.
--distpath <path>: 打包到哪个目录下
-w: 指定生成 GUI 软件,也就是运行时不打开控制台
-c: 运行时打开控制台
-i <Icon File>: 指定打包后可执行文件的图标
--clean: 在构建之前清理PyInstaller缓存并删除临时文件
위의 프로젝트 예제는 여기에서도 여전히 사용되지만 setuptools
패키징과 달리 단일 모듈의 항목 기능 만 여기에 패키징됩니다pdf_task
main.py
( 루트 디렉터리 main.py
에 있음).GUI 데스크탑이 포함되지 않으므로 콘솔 출력이 유지되고 패키징 명령은 명령은 다음과 같습니다.pdf_task
(spider_env) PS D:\桌面\pypi_test> pyinstaller --distpath D:/pypi_package/Release/ --clean pdf_task/main.py
pypi_test
패키징 후 현재 디렉터리( ) 아래에 폴더 build
가 생성되고 , 경로 아래에 릴리스 버전 의 패키지 파일 distpath
( )이 생성됩니다 .Release
2) 패키지 및 정적 파일 가져오기 문제
참고 :
-
패키징할 때 모듈의 루트 디렉터리 (여기서는 ) 아래에
main.py
두어야 하며 파일을 패키지의 다른 모듈로 가져올 때 루트 디렉터리 이름을 추가해야 합니다 .pdf_task
python
import
예를 들어, 다음과 같은
Release
실행 파일을 실행하면No module named 'pdf_handler'
오류가 발생합니다.from pdf_handler import extract_pdf_text,extract_pdf_table,split_pdf import os if __name__ == '__main__': print("Hello world") extract_pdf_text() extract_pdf_table() split_pdf() os.system("pause")
pdf_handler
찾을 수 없는 오류가 보고되지 않도록 다음 가져오기 방법으로 수정해야 합니다 ( 전제는pdf_task
빈 패키지를 포함해야 하는 Python 패키지라는__init__.py
것입니다 . 그렇지 않으면 오류가 보고됨).from pdf_task.pdf_handler import extract_pdf_text,extract_pdf_table,split_pdf import os if __name__ == '__main__': print("Hello world") extract_pdf_text() extract_pdf_table() split_pdf() os.system("pause")
-
Release
위 폴더를 직접 실행하면main.exe
아래와 같은 오류가 발생합니다.참고 : 콘솔이 깜박이면 GUI 인터페이스와 함께 명령을 사용하여
pyinstaller --distpath D:/pypi_package/Release/ -w --clean pdf_task/main.py
인터페이스에서 오류 메시지를 볼 수 있습니다.오류 메시지를 찾은 다음 누락된 정적 파일 (구성 파일 또는 정적 코드 라이브러리) 을 도입하려는 경우 에서 사용할 수 있습니다
python
raise Exception()
.Traceback (most recent call last): File "pdf_task\main.py", line 6, in <module> File "pdf_task\pdf_handler.py", line 17, in extract_pdf_text File "pdfplumber\pdf.py", line 71, in open FileNotFoundError: [Errno 2] No such file or directory: 'D:\\桌面\\pypi_test\\src\\Release\\main\\pdf_task\\resume.pdf'
해결책은 모듈의 정적 파일을 그대로 복사 하는 것입니다
Release/main
( 전체를 복사 하고 불필요한 파일은pdf_task
모두 삭제py
).이렇게 하면 폴더를 다시 실행
Release
해도main.exe
문제가 없습니다 .
3) 기타 문제
-
프로젝트에 GUI 인터페이스가 없지만
pyinstaller
-w
패키징 할 때 옵션이 실수로 사용되어 프로그램이 시작된 후 작업에 사용할 수 있는 닫기 버튼이 없는 경우 여기에서 프로그램을 종료하려는 경우 다음과job_scheduler.exe
같이 가정합니다.windows10
, 다음을 수행할 수 있습니다( Windows 환경에서 CMD 콘솔을 참조하여 프로세스를 보고 프로세스 관련 명령 | Programmer Sought 참조 ).C:\Users\THINKPAD>tasklist | findstr job_scheduler.exe job_scheduler.exe 42180 Console 1 170,928 K C:\Users\THINKPAD>tasklist /f /t /im job_scheduler.exe 错误: 无效参数/选项 - '/f'。 键入 "TASKLIST /?" 以了解用法。 C:\Users\THINKPAD>taskkill /f /t /im job_scheduler.exe 成功: 已终止 PID 42180 (属于 PID 10888 子进程)的进程。
작업 관리자에서 찾을 수 있으면 괜찮습니다.
-
windows10
Win10 시스템에서 booting_RobVisual_RobVisual 후 자동 시작을 위한 소프트웨어(.exe 실행 프로그램) 설정 방법exe
참조 -
exe
실행 파일을 인터넷에 게시 하려면 공식 튜토리얼인 What is Release(릴리스 버전) - Gitee.com을gitee
참조하십시오.
4. 환경 복사 및 실행 스크립트 작성
여전히 위의 pypi_test
모듈을 pdf_task
예로 들어, 동일한 운영 체제에서 압축된 패키지의 압축을 푼 후 다른 사람이 직접 메서드를 호출하도록 하려면 환경을 프로젝트의 루트 디렉터리에 직접 복사하고 시작 스크립트를 작성할 pdf_task/main.py
수 있습니다 .python
main.py
-
python
가상 환경spider_env
의 모든 파일을 루트 디렉터리에 직접 복사합니다py38
. -
시작 스크립트를 작성하고 실행하여
main.py
;py38\python.exe pdf_task\main.py pause
프로젝트 구조는 다음과 같습니다.
setuptools
패키징 과 달리 환경을 pyInstaller
직접 복사하는 장점은 원래 프로젝트 구조의 무결성을 보장할 수 있다는 점이지만 단점은 다른 시스템으로의 이식성이 상대적으로 떨어진다는 것입니다 .Python