จะเขียนโมดูล / แพ็คเกจ Python ได้อย่างไร?


375

ฉันได้สร้างสคริปต์ Python สำหรับงานง่าย ๆ ในที่ทำงานและไม่เคยใส่ใจในการบรรจุพวกเขาให้ผู้อื่นใช้ ตอนนี้ฉันได้รับมอบหมายให้ทำ wrapper Python สำหรับ REST API ฉันไม่รู้ว่าจะเริ่มอย่างไรและต้องการความช่วยเหลือ

สิ่งที่ฉันมี:

(แค่ต้องการเจาะจงให้มากที่สุดเท่าที่จะทำได้) ฉันมีvirtualenv ให้พร้อมแล้วมันก็ขึ้นใน githubไฟล์. gitignore สำหรับ python ก็มีอยู่เช่นกันรวมถึงไลบรารีคำขอสำหรับการโต้ตอบกับ REST API แค่นั้นแหละ.

นี่คือแผนผังไดเรกทอรีปัจจุบัน

.
├── bin
   └── /the usual stuff/
├── include
   └── /the usual stuff/
├── lib
   └── python2.7
       └── /the usual stuff/
├── local
   └── /the usual stuff/
└── README.md

27 directories, 280 files

ฉันไม่รู้ด้วยซ้ำว่าจะวางไฟล์. py ไว้ที่ใดหากฉันสร้างไฟล์ขึ้นมา

สิ่งที่ฉันต้องการจะทำ:

ทำให้โมดูล python สามารถติดตั้งได้ด้วย "pip install ... "

ถ้าเป็นไปได้ฉันต้องการกระบวนการทั่วไปทีละขั้นตอนในการเขียนโมดูล Python


15
ฉันจะเริ่มต้นด้วยบทที่ 6 ของบทช่วยสอน (2.7)หรือที่นี่เพื่อ 3.x ค้นหาอินเทอร์เน็ตสำหรับบทเรียนเกี่ยวกับโมดูลหลามและคุณจะพบคนอื่นอีกมากมาย
Roland Smith เมื่อ

6
ไม่มีใครตอบส่วนของ pip
whackamadoodle3000

github.com/MacHu-GWU/pygitrepo-projectห้องสมุดนี้ช่วยให้คุณสร้างโครงกระดูกโครงการตั้งแต่เริ่มต้นและคุณลักษณะที่คุณต้องการไม่อยู่ในกรอบ
MacSanhe

คำตอบ:


424

โมดูลเป็นไฟล์ที่มีคำจำกัดความและคำสั่ง Python ชื่อไฟล์คือชื่อโมดูลที่มีคำต่อท้าย.py

สร้างhello.pyแล้วเขียนฟังก์ชั่นต่อไปนี้เป็นเนื้อหา:

def helloworld():
   print "hello"

จากนั้นคุณสามารถนำเข้าhello:

>>> import hello
>>> hello.helloworld()
'hello'
>>>

ในการจัดกลุ่ม.pyไฟล์จำนวนมากวางไว้ในโฟลเดอร์ โฟลเดอร์ใด ๆ ที่มีการ__init__.pyพิจารณาเป็นโมดูลโดยหลามและคุณสามารถเรียกพวกเขาแพคเกจ

|-HelloModule
  |_ __init__.py
  |_ hellomodule.py

คุณสามารถไปกับคำสั่งการนำเข้าในโมดูลของคุณด้วยวิธีปกติ

สำหรับข้อมูลเพิ่มเติมดูที่6.4 แพคเกจ


7
อันสุดท้ายจะเป็น: จาก HellowModule นำเข้า hellomodule หรือไม่ อาจเป็นสวัสดีในโฟลเดอร์โมดูลดังนั้นมันจะมาจากการนำเข้า HelloModule hello
nycynik

ขณะนี้กำลังเล่นกับ Python และคำตอบนี้จะเป็นประโยชน์อย่างหนึ่งที่ฉันได้พบ อธิบายได้ดีมากขอบคุณ
Darren Wainwright

คำสั่ง "pip install" จะไม่ทำงานนอกจากนี้คุณต้องอยู่ในไดเรกทอรีเดียวกันเพื่อใช้งาน
Math Coder 101

234

Python 3 - อัปเดต 18 พฤศจิกายน 2558

พบคำตอบที่ยอมรับแล้วมีประโยชน์ แต่ต้องการขยายในหลาย ๆ จุดเพื่อประโยชน์ของผู้อื่นตามประสบการณ์ของฉันเอง

โมดูล:โมดูลเป็นไฟล์ที่มีคำจำกัดความและคำสั่ง Python ชื่อไฟล์คือชื่อโมดูลที่ต่อท้าย. py ต่อท้าย

ตัวอย่างโมดูล : สมมติว่าเรามีสคริปต์หลามเดียวในไดเรกทอรีปัจจุบันที่นี่ฉันกำลังเรียกมันว่าmymodule.py

ไฟล์mymodule.pyมีรหัสต่อไปนี้:

def myfunc():
    print("Hello!")

หากเราเรียกใช้ตัวแปล python3 จากไดเรกทอรีปัจจุบันเราสามารถนำเข้าและเรียกใช้ฟังก์ชันmyfuncด้วยวิธีการต่าง ๆ ดังต่อไปนี้ (โดยทั่วไปคุณจะเลือกหนึ่งในรายการต่อไปนี้):

>>> import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mymodule import myfunc
>>> myfunc()
Hello!
>>> from mymodule import *
>>> myfunc()
Hello!

ตกลงดังนั้นง่ายพอ

ทีนี้สมมติว่าคุณมีความจำเป็นที่จะต้องวางโมดูลนี้ลงในโฟลเดอร์เฉพาะของตนเองเพื่อจัดเตรียมเนมสเปซโมดูลแทนที่จะเรียกใช้เพียงเฉพาะกิจจากไดเรกทอรีการทำงานปัจจุบัน ซึ่งเป็นที่ที่จะมีมูลค่าการอธิบายแนวคิดของการเป็นแพคเกจ

แพ็คเกจ : แพ็คเกจเป็นวิธีการสร้างเนมสเปซโมดูลของ Python โดยใช้“ ชื่อโมดูลประ” ตัวอย่างเช่นชื่อโมดูล AB กำหนด submodule ชื่อ B ในแพ็คเกจชื่อ A. เช่นเดียวกับการใช้โมดูลจะบันทึกผู้เขียนของโมดูลที่แตกต่างกันโดยไม่ต้องกังวลเกี่ยวกับชื่อตัวแปรส่วนกลางของกันและกันการใช้ชื่อโมดูลประจะบันทึกผู้เขียน ของแพ็คเกจหลายโมดูลเช่น NumPy หรือ Python Imaging Library ไม่ต้องกังวลเกี่ยวกับชื่อโมดูลของกันและกัน

ตัวอย่างแพคเกจ : ตอนนี้สมมติว่าเรามีโฟลเดอร์และไฟล์ต่อไปนี้ ที่นี่mymodule.pyเหมือนก่อนหน้าและ__init__.pyเป็นไฟล์ว่างเปล่า:

.
└── mypackage
    ├── __init__.py
    └── mymodule.py

จำเป็นต้องใช้ไฟล์ __init__.py เพื่อให้ Python จัดการกับไดเรกทอรีที่มีแพ็คเกจ สำหรับข้อมูลเพิ่มเติมโปรดดูลิงค์เอกสารประกอบโมดูลที่ให้ไว้ในภายหลัง

ไดเรกทอรีการทำงานปัจจุบันของเราคือหนึ่งระดับเหนือโฟลเดอร์ปกติที่เรียกว่าmypackage

$ ls
mypackage

หากเราเรียกใช้ตัวแปล python3 ในตอนนี้เราสามารถนำเข้าและเรียกใช้โมดูลmymodule.pyซึ่งมีฟังก์ชั่นที่จำเป็นต้องใช้myfuncด้วยวิธีการต่าง ๆ ดังต่อไปนี้

>>> import mypackage
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> import mypackage.mymodule
>>> mypackage.mymodule.myfunc()
Hello!
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mypackage.mymodule import myfunc
>>> myfunc()
Hello!
>>> from mypackage.mymodule import *
>>> myfunc()
Hello!

สมมติว่า Python 3 มีเอกสารที่ยอดเยี่ยมที่: Modules

ในแง่ของการตั้งชื่อแบบแผนสำหรับแพ็คเกจและโมดูลแนวทางทั่วไปมีให้ใน PEP-0008 - โปรดดูชื่อแพคเกจและโมดูล

โมดูลควรมีชื่อแบบย่อและตัวพิมพ์เล็กทั้งหมด สามารถใช้เครื่องหมายขีดล่างในชื่อโมดูลได้หากมีการปรับปรุงความสามารถในการอ่าน แพ็คเกจ Python ควรมีชื่อสั้นและตัวพิมพ์เล็กทั้งหมดแม้ว่าการใช้เครื่องหมายขีดล่างจะไม่ได้รับการสนับสนุน


5
คำอธิบายง่ายๆดี ถ้าคุณต้องการเก็บโฟลเดอร์อื่นไว้ใน mypackage
Anuj Gupta

3
การรวมขึ้นอยู่กับสิ่งที่คุณเขียน import mypackageในกรณีที่คุณนำสิ่งที่อยู่นอกฟังก์ชั่นในโมดูลของคุณคุณจะยิงมันเมื่อโทรเช่น ในกรณีที่คุณต้องการที่จะนำเข้าเพียงฟังก์ชั่นจากโมดูล (แม้ไฟล์) from module import functionดีกว่าที่จะใช้ ในกรณีที่โฟลเดอร์ย่อยfrom subfolder.module import functionเพื่อให้คุณสามารถเรียกfunction()witthout ส่วนรหัสอื่น ๆ นอกจากนี้อย่าใช้from module import *ถ้าคุณไม่ต้องการจริงๆ
m3nda

5
คำถามเดียวที่เหลือคือฉันจะนำแพคเกจเพื่อนำเข้าทุกอย่างได้import mypackageอย่างไร กำลังเพิ่มimport mymoduleลงไป__init__.pyไม่ทำงาน ..
576i

คำอธิบายที่เรียบร้อย! อย่างไรก็ตามฉันมีคำถามว่า numpy เป็นแพ็คเกจฉันจะเรียกใช้ numpy.cos (1) ในล่ามของฉันได้อย่างไรเพราะนั่นดูเหมือนจะเป็นชื่อโมดูลระหว่างที่หายไป ไม่มี?
user1935724

3
แล้ว pip ล่ะ
whackamadoodle3000

199

เนื่องจากยังไม่มีใครครอบคลุมคำถามของ OP นี้:

สิ่งที่ฉันต้องการจะทำ:

ทำให้โมดูล python สามารถติดตั้งได้ด้วย "pip install ... "

นี่คือตัวอย่างที่น้อยที่สุดแน่นอนแสดงขั้นตอนพื้นฐานของการเตรียมความพร้อมและการอัปโหลดแพคเกจของคุณเพื่อ PyPI ใช้และsetuptoolstwine

นี่ไม่ใช่วิธีที่ใช้แทนการอ่านบทช่วยสอนอย่างน้อยก็มีมากกว่าที่ครอบคลุมในตัวอย่างพื้นฐานนี้

การสร้างแพ็กเกจนั้นถูกครอบคลุมโดยคำตอบอื่น ๆ ที่นี่ดังนั้นให้เราคิดว่าเรามีขั้นตอนที่ครอบคลุมและโครงสร้างโครงการของเราดังนี้:

.
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

เพื่อที่จะใช้ setuptoolsสำหรับบรรจุภัณฑ์เราจำเป็นต้องเพิ่มไฟล์setup.pyเข้าไปในโฟลเดอร์รากของโครงการของเรา:

.
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

อย่างน้อยที่สุดเราระบุข้อมูลเมตาสำหรับแพ็คเกจของเราเราsetup.pyจะมีลักษณะดังนี้:

from setuptools import setup

setup(
    name='hellostackoverflow',
    version='0.0.1',
    description='a pip-installable package example',
    license='MIT',
    packages=['hellostackoverflow'],
    author='Benjamin Gerfelder',
    author_email='benjamin.gerfelder@gmail.com',
    keywords=['example'],
    url='https://github.com/bgse/hellostackoverflow'
)

เนื่องจากเราได้ตั้งค่าไว้license='MIT'เราจึงรวมสำเนาในโครงการของเราเป็นLICENCE.txtพร้อมกับไฟล์ readme ใน reStructuredText เป็นREADME.rst:

.
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

ณ จุดนี้เราพร้อมที่จะเริ่มใช้บรรจุภัณฑ์ setuptoolsหากเรายังไม่ได้ติดตั้งเราสามารถติดตั้งได้ด้วยpip:

pip install setuptools

ในการทำและสร้าง a source distribution, ในโฟลเดอร์รูทโปรเจคของเราเราเรียกว่าsetup.pyจากบรรทัดคำสั่งโดยระบุว่าเราต้องการsdist:

python setup.py sdist

สิ่งนี้จะสร้างแพ็คเกจการกระจายสินค้าและข้อมูลไข่ของเราและส่งผลให้โครงสร้างโฟลเดอร์เช่นนี้กับแพ็คเกจของเรา dist :

.
├── dist/
├── hellostackoverflow.egg-info/
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

ณ จุดนี้เรามีแพ็คเกจที่เราสามารถติดตั้งโดยใช้ pipดังนั้นจากรูทโครงการของเรา (สมมติว่าคุณมีการตั้งชื่อทั้งหมดในตัวอย่างนี้):

pip install ./dist/hellostackoverflow-0.0.1.tar.gz

หากทุกอย่างไปได้ด้วยดีตอนนี้เราสามารถเปิด Python interpreter ได้ฉันจะพูดว่าอยู่นอกไดเรกทอรีโครงการของเราเพื่อหลีกเลี่ยงความสับสนและลองใช้แพ็คเกจใหม่ของเรา:

Python 3.5.2 (default, Sep 14 2017, 22:51:06) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from hellostackoverflow import hellostackoverflow
>>> hellostackoverflow.greeting()
'Hello Stack Overflow!'

ตอนนี้เราได้ยืนยันการติดตั้งและการทำงานของแพ็คเกจแล้วเราสามารถอัปโหลดไปยัง PyPI ได้

เนื่องจากเราไม่ต้องการสร้างที่เก็บข้อมูลสดด้วยการทดลองของเราเราจึงสร้างบัญชีสำหรับที่เก็บการทดสอบและติดตั้งtwineสำหรับกระบวนการอัปโหลด:

pip install twine

ตอนนี้เราเกือบจะอยู่ที่นั่นด้วยบัญชีของเราที่สร้างขึ้นเราก็บอก twineให้อัพโหลดแพ็คเกจของเรามันจะขอข้อมูลประจำตัวของเราและอัปโหลดแพ็คเกจของเราไปยังพื้นที่เก็บข้อมูลที่ระบุ:

twine upload --repository-url https://test.pypi.org/legacy/ dist/*

ตอนนี้เราสามารถลงชื่อเข้าใช้บัญชีของเราในที่เก็บการทดสอบ PyPI และประหลาดใจกับแพ็คเกจที่อัปโหลดใหม่ของเราสักครู่แล้วคว้ามันโดยใช้pip:

pip install --index-url https://test.pypi.org/simple/ hellostackoverflow

อย่างที่เราเห็นกระบวนการขั้นพื้นฐานไม่ซับซ้อนมาก อย่างที่ผมพูดไปก่อนหน้านี้มีอะไรมากกว่าที่กล่าวถึงข้างต้นดังนั้นไปข้างหน้าและอ่านบทช่วยสอนสำหรับคำอธิบายเชิงลึกเพิ่มเติม


แพ็คเกจของฉันจะถูกเผยแพร่หลังจากนี้setuptoolsหรือไม่
ส่งต่อ

@ U9 ไปข้างหน้าไม่มีการประกาศจะทำด้วยแต่คุณสามารถทดสอบแพคเกจของคุณภายในก่อนที่จะเผยแพร่หลังจากที่คุณสร้างมันขึ้นมาด้วยtwine setuptools
bgse

9

เมื่อคุณได้กำหนดคำสั่งที่คุณเลือกคุณสามารถลากและวางไฟล์ที่บันทึกไว้ในโฟลเดอร์ Lib ในไฟล์โปรแกรมหลาม

>>> import mymodule 
>>> mymodule.myfunc()

2

ทำไฟล์ชื่อ "hello.py"

ถ้าคุณใช้ Python 2.x

def func():
    print "Hello"

ถ้าคุณใช้ Python 3.x

def func():
    print("Hello")

เรียกใช้ไฟล์ จากนั้นคุณสามารถลองทำสิ่งต่อไปนี้:

>>> import hello
>>> hello.func()
Hello

หากคุณต้องการยากสักหน่อยคุณสามารถใช้สิ่งต่อไปนี้:

ถ้าคุณใช้ Python 2.x

def say(text):
    print text

ถ้าคุณใช้ Python 3.x

def say(text):
    print(text)

ดูสิ่งที่อยู่ในวงเล็บข้างคำจำกัดความหรือไม่ นั่นเป็นสิ่งสำคัญ มันเป็นสิ่งที่คุณสามารถใช้ภายในการกำหนด

ข้อความ - คุณสามารถใช้มันเมื่อคุณต้องการให้โปรแกรมพูดสิ่งที่คุณต้องการ ตามชื่อมันเป็นข้อความ ฉันหวังว่าคุณจะรู้ว่าข้อความหมายถึงอะไร มันหมายถึง "คำ" หรือ "ประโยค"

เรียกใช้ไฟล์ จากนั้นคุณสามารถลองทำสิ่งต่อไปนี้หากคุณใช้ Python 3.x:

>>> import hello
>>> hello.say("hi")
hi
>>> from hello import say
>>> say("test")
test

สำหรับ Python 2.x - ฉันเดาแบบเดียวกันกับ Python 3 ไม่มีความเห็น. แก้ไขให้ถูกต้องหากฉันทำผิดกับ Python 2.x (ฉันรู้จัก Python 2 แต่ฉันใช้กับ Python 3)


2

ฉันสร้างโครงการเพื่อให้ง่ายต่อการเริ่มต้นโครงการโครงกระดูกจากรอยขีดข่วน https://github.com/MacHu-GWU/pygitrepo-projecthttps://github.com/MacHu-GWU/pygitrepo-project

และคุณสามารถสร้างโครงการทดสอบสมมุติว่า learn_creating_py_packageและคุณสามารถสร้างโครงการทดสอบสมมติว่า

คุณสามารถเรียนรู้องค์ประกอบที่คุณควรมีเพื่อจุดประสงค์ที่แตกต่างกันเช่น :

  • สร้าง virtualenv
  • ติดตั้งตัวเอง
  • เรียกใช้ unittest
  • เรียกใช้ครอบคลุมรหัส
  • สร้างเอกสาร
  • ปรับใช้เอกสาร
  • เรียกใช้ไม่ได้ในเวอร์ชัน python ที่ต่างกัน
  • ปรับใช้กับ PYPI

ประโยชน์ของการใช้pygitrepoเป็นที่น่าเบื่อเหล่านี้จะสร้างตัวเองโดยอัตโนมัติและปรับของคุณpackage_name, project_name, github_account, document host service,windows or macos or linux ,

เป็นสถานที่ที่ดีในการเรียนรู้การพัฒนาโครงการหลามอย่างมืออาชีพ

หวังว่านี่จะช่วยได้

ขอบคุณ.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.