การติดตั้งโมดูลหลามภายในรหัส


310

ฉันต้องติดตั้งแพคเกจจาก PyPi โดยตรงภายในสคริปต์ของฉัน อาจจะมีบางโมดูลหรือdistutils ( distribute, pipฯลฯ ) ที่ช่วยให้ฉันเพียงแค่ดำเนินการบางอย่างเช่นpypi.install('requests')และคำขอจะถูกติดตั้งลงใน virtualenv ของฉัน


4
ทำไมคุณไม่กำหนดโมดูลที่เกี่ยวข้องเป็นการอ้างอิงใน setup.py ของแพ็คเกจของคุณเอง
Andreas Jung

5
คุณรู้ ... วิธีที่ควรจะทำจริง ๆ ... แต่คุณสามารถ os.system ("pip install blah") ได้ตลอดเวลา แต่คุณอาจต้องใช้ sudo access ... ดีกว่าเพื่อให้มันขึ้นอยู่กับการตั้งค่าของคุณ py
Joran Beasley

2
คุณจะพิจารณาเปลี่ยนคำตอบที่ยอมรับได้ที่นี่หรือไม่ การนำเข้าpipไม่ใช่ความคิดที่ดีความจริงเพียงว่าเนื้อหาทั้งหมด_internalเริ่มตั้งแต่รุ่น 10 ...
Antti Haapala

2
@chuwy stackoverflow.com/a/50255019/918959 <= อันนี้ pip._internalไม่ได้ออกแบบมาให้นำเข้าได้ก็สามารถทำสิ่งสุ่มอย่างเมื่อนำเข้าในโปรแกรมอื่น
Antti Haapala

3
@AnttiHaapala ตกลงฉันเปลี่ยนมัน โดยส่วนตัวฉันไม่ชอบวิธีแก้ปัญหาทั้งสองอย่าง แต่ฉันอยู่ห่างไกลจาก Python ในปัจจุบันดังนั้นฉันจึงเชื่อมั่นในความคิดเห็นของคุณ
chuwy

คำตอบ:


253

วิธีที่แนะนำอย่างเป็นทางการในการติดตั้งแพคเกจจากสคริปต์คือการเรียกอินเตอร์เฟสบรรทัดคำสั่งของ pip ผ่านกระบวนการย่อย คำตอบอื่น ๆ ส่วนใหญ่นำเสนอที่นี่จะไม่ได้รับการสนับสนุนโดย pip นอกจากนี้ตั้งแต่ pip v10 รหัสทั้งหมดจึงถูกย้ายไปpip._internalแม่นยำเพื่อให้ชัดเจนกับผู้ใช้ว่าไม่อนุญาตให้ใช้ pip แบบเป็นโปรแกรม

ใช้sys.executableเพื่อให้แน่ใจว่าคุณจะโทรติดต่อเดียวกันpipกับที่เกี่ยวข้องกับรันไทม์ปัจจุบัน

import subprocess
import sys

def install(package):
    subprocess.check_call([sys.executable, "-m", "pip", "install", package])

ปัญหาหนึ่งของเรื่องนี้คือสำหรับผู้ใช้มือใหม่บน Windows, python และ pip ​​ไม่ได้อยู่ใน PATH เสมอไปดังนั้นไฟล์. py ที่สามารถดับเบิลคลิกได้จะสะดวกมากในขณะที่ "pip install xxx" สามารถแสดงความคิดเห็นได้ ค่อนข้างยุ่งยาก
jdpipe

CalledProcessError: คำสั่ง '[' C: \\ ProgramData \\ Anaconda3 \\ pythonw.exe ',' -m ',' pip ',' pip ',' ติดตั้ง ',' googleapiclient ']' ส่งคืนสถานะทางออกที่ไม่ใช่ศูนย์ 1
parvij

383

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

import pip

def install(package):
    if hasattr(pip, 'main'):
        pip.main(['install', package])
    else:
        pip._internal.main(['install', package])

# Example
if __name__ == '__main__':
    install('argh')

3
@nbro คุณจะส่งผ่านตัวเลือกไปที่pip.main()ตามที่คุณต้องการในบรรทัดคำสั่ง (แต่ด้วยตัวเลือกแต่ละรายการเป็นรายการแยกต่างหากในรายการแทนที่จะเป็นสตริงเดียว) และเพื่อระบุเวอร์ชันของแพ็กเกจที่คุณต้องการให้ทำเช่นเดียวกับในบรรทัดคำสั่ง .. ex:pip.main(['install', 'pip==7.1.0'])
Kaos

3
ดูstackoverflow.com/questions/6457794/…ซึ่งแสดงวิธีจัดการกรณีและปัญหาที่การติดตั้งล้มเหลว
P. Myer Nore

25
from pip._internal import main as pipmainจากนั้นคุณสามารถใช้pipmain()เช่นเดียวกับที่คัดค้านpip.main()ดูstackoverflow.com/questions/43398961/ …
แฟนคลับหมายเลขหนึ่งของ Bjorks

17
depreceated มันตอนนี้
มอร์ส

6
มันเลิกใช้แล้วด้วยเหตุผล & ไม่แนะนำอีกต่อไป ดูpip.pypa.io/en/latest/user_guide/#using-pip-from-your-program
NBK

71

หากคุณต้องการใช้pipเพื่อติดตั้งแพคเกจที่จำเป็นและนำเข้ามันหลังการติดตั้งคุณสามารถใช้รหัสนี้:

def install_and_import(package):
    import importlib
    try:
        importlib.import_module(package)
    except ImportError:
        import pip
        pip.main(['install', package])
    finally:
        globals()[package] = importlib.import_module(package)


install_and_import('transliterate')

หากคุณติดตั้งแพ็คเกจในฐานะผู้ใช้คุณสามารถพบปัญหาที่คุณไม่สามารถนำเข้าแพ็คเกจได้ ดูวิธีการรีเฟรช sys.path สำหรับข้อมูลเพิ่มเติม


4
มีความคิดใดที่จะทำเช่นนั้นใน Python 3 imp.reload(site)ทำให้ฉันได้RuntimeError: dictionary changed size during iteration
kgadek

pip uninstall <package_name>ที่นี้ไม่ได้ติดตั้งแพคเกจหลังจากที่ฉันทำอย่างนี้ผมไม่สามารถที่จะทำ ฉันยังคงสามารถถอนการติดตั้งโดยใช้pip.mainแต่แค่อยากจะรู้ว่ามันติดตั้งแพคเกจ?
Ishan Khare

อยากรู้อยากเห็น มันจะทำงานได้อย่างถูกต้องpip install requests[security]หรือไม่ถ้าฉัน: ฉันไม่แน่ใจว่ามันจะกำหนดกลมได้อย่างถูกต้องหรือไม่
Fallenreaper

4
เก่า. pip.mainไม่ทำงานอีกต่อไป pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program
Wim

23

สิ่งนี้น่าจะใช้ได้:

import subprocess

def install(name):
    subprocess.call(['pip', 'install', name])

1
ใช่มันควรจะทำงานได้อย่างแน่นอน แต่ฉันคิดว่ามีวิธีที่สง่างามกว่า;) ฉันจะรอสักหน่อยอาจจะมี
chuwy

1
@Downvoter: มีอะไรผิดปกติกับคำตอบของฉัน? คำตอบนี้ต้องการ OP ทั้งหมด มันไม่ได้ใช้เปลือก
ควอนตัม

13
ขึ้นอยู่กับรุ่นที่ถูกต้องของ pip ที่เป็นคนแรกบนเส้นทาง หากผู้ใช้กำลังติดตั้ง python สำรอง pip จะติดตั้งลงในอันแรกแทนการติดตั้งปัจจุบัน วิธีการนำเข้าข้างต้นจะติดตั้งในตำแหน่งที่ถูกต้อง ฉัน upvoted อยู่แล้วเพื่อตอบโต้การลงคะแนน
GaryBishop

6
ขึ้นอยู่กับว่าสคริปต์ทำงานอย่างไรคุณจะไม่เรียก pip ที่ถูกต้อง
Natim

5
การโทร[sys.executable, '-m', 'pip', 'install', name]ทำให้แน่ใจว่าได้รับ pip ที่ "ถูกต้อง" ที่นี่
Wim

12

ฉันได้เพิ่มข้อยกเว้นในการจัดการกับคำตอบของ @ Aaron

import subprocess
import sys

try:
    import pandas as pd
except ImportError:
    subprocess.check_call([sys.executable, "-m", "pip", "install", 'pandas'])
finally:
    import pandas as pd

1
ใช้งาน subprocess และ pip ​​ได้ดีกว่าโซลูชันส่วนใหญ่ที่นี่
Shantanu Shady

3
คุณไม่ได้ตรวจสอบค่า retunr subprocess.callเพื่อให้รหัสอาจล้มเหลว
Antti Haapala

5

คุณกำหนดโมดูลที่ต้องพึ่งพาภายใน setup.py ของแพ็คเกจของคุณเองด้วยตัวเลือก "install_requires"

หากแพ็กเกจของคุณต้องสร้างสคริปต์คอนโซลบางตัวคุณสามารถใช้จุดเริ่มต้น "console_scripts" เพื่อสร้างสคริปต์ตัวตัดคำที่จะอยู่ในโฟลเดอร์ 'bin' (เช่นสภาพแวดล้อม virtualenv ของคุณ)


1
นี่คือคำตอบที่ถูกต้องและเป็นวิธีเดียวที่เหมาะสมในการจัดการการพึ่งพาของโครงการ Python มันจะทำงานร่วมกับ virtualenv, Fabric, buildout คุณตั้งชื่อมัน วิธีการที่อธิบายโดย @xiaomao แม้ว่าการตอบกลับอย่างที่ OP ต้องการคือความบ้าคลั่ง
Lukas Graf

7
ในขณะที่นี่เป็นคำแนะนำที่เหมาะสม แต่ก็ไม่ตอบคำถามที่ถาม
Corey Goldberg

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