पायथन: वर्तमान चल रहे स्क्रिप्ट के सापेक्ष sys.path को जोड़ने का सबसे अच्छा तरीका


98

मेरे पास स्क्रिप्ट से भरा एक निर्देशिका है (चलो कहते हैं project/bin)। मेरे पास एक पुस्तकालय भी है, project/libऔर स्क्रिप्ट को स्वचालित रूप से लोड करना चाहते हैं। यह वही है जो मैं आमतौर पर प्रत्येक स्क्रिप्ट के शीर्ष पर उपयोग करता हूं:

#!/usr/bin/python
from os.path import dirname, realpath, sep, pardir
import sys
sys.path.append(dirname(realpath(__file__)) + sep + pardir + sep + "lib")

# ... now the real code
import mylib

यह एक प्रकार का बोझिल, बदसूरत है, और इसे हर फ़ाइल की शुरुआत में चिपकाया जाना है। क्या ऐसा करने के लिए इससे अच्छा तरीका है?

वास्तव में मैं जिस चीज की उम्मीद कर रहा हूं वह कुछ इस तरह चिकनी है:

#!/usr/bin/python
import sys.path
from os.path import pardir, sep
sys.path.append_relative(pardir + sep + "lib")

import mylib

या इससे भी बेहतर, कुछ ऐसा नहीं होगा जो मेरे संपादक (या किसी और के पास, जिसने पहुंच बनाई हो) अपनी साफ-सफाई की प्रक्रिया के तहत आयात को फिर से शुरू करने का फैसला करता है:

#!/usr/bin/python --relpath_append ../lib
import mylib

यह सीधे नॉन-पॉसिक्स प्लेटफार्मों पर पोर्ट नहीं करेगा, लेकिन यह चीजों को साफ रखेगा।


1
इन्हें भी देखें: stackoverflow.com/questions/2349991/…
dreftymac

जवाबों:


26

यदि आप प्रत्येक फ़ाइल को संपादित नहीं करना चाहते हैं

  • आप एक सामान्य अजगर लाइब्राय की तरह पुस्तकालय स्थापित करें
    या
  • PYTHONPATHअपने को सेट करेंlib

या यदि आप प्रत्येक फ़ाइल में एक पंक्ति जोड़ने के लिए तैयार हैं, तो शीर्ष पर आयात विवरण जोड़ें

import import_my_lib

import_my_lib.pyबिन में रखें और import_my_libजो कुछ भी libआप चाहते हैं उसे सही ढंग से अजगर पथ निर्धारित कर सकते हैं


118

यही है वह जो मेरे द्वारा उपयोग किया जाता है:

import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), "lib"))

2
मैं sys.path.insert (0, ..) करूंगा ताकि यह अन्य रास्तों से ओवरराइड न हो।
जॉन जियांग

क्या वास्तव में इसे स्वचालित रूप से चलाने का कोई तरीका नहीं है?
डेनिस डे बर्नार्डी

1
यह थोड़ा जोखिम भरा है। यदि __file__वर्तमान कार्यशील निर्देशिका के लिए एक रिश्तेदार फ़ाइल नाम रिश्तेदार है (जैसे, setup.py), तो os.path.dirname(__file__)हो जाएगा रिक्त स्ट्रिंग। इस और जॉन जियांग द्वारा उठाए गए समान चिंताओं के लिए , एखुमोरो का अधिक सामान्य उद्देश्य समाधान दृढ़ता से बेहतर है।
सेसिल करी

29

मैं उपयोग कर रहा हूँ:

import sys,os
sys.path.append(os.getcwd())

5
मैं अक्सर बस करता हूँsys.path.append('.')
किम्बो

1
क्या होगा यदि स्क्रिप्ट को अलग निर्देशिका से चलाया जा रहा है? पूर्ण सिस्टम पथ देकर रूट निर्देशिका से उदाहरण के लिए? तब os.getcwd () वापस आएगा "/"
obayhan

2
ऐसा कभी न करें। वर्तमान कामकाजी निर्देशिका (CWD) की गारंटी नहीं है कि आप क्या सोचते हैं - विशेष रूप से अप्रत्याशित किनारे के मामलों के तहत, आपको निश्चित रूप से एक मील दूर आते हुए देखा जाना चाहिए। __file__इसके बजाय किसी भी अर्ध-डेवलपर डेवलपर के बजाय संदर्भ ।
सेसिल करी

14

एक आवरण मॉड्यूल बनाएँ project/bin/lib, जिसमें यह शामिल है:

import sys, os

sys.path.insert(0, os.path.join(
    os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib'))

import mylib

del sys.path[0], sys, os

फिर आप अपनी स्क्रिप्ट के शीर्ष पर सभी क्रुफ़्ट को बदल सकते हैं:

#!/usr/bin/python
from lib import mylib

8

यदि आप किसी भी तरह से स्क्रिप्ट सामग्री को बदलना नहीं चाहते हैं, तो वर्तमान कार्यशील निर्देशिका .को PYTHONPATH (नीचे उदाहरण देखें) के लिए प्रस्तुत करें

PYTHONPATH=.:$PYTHONPATH alembic revision --autogenerate -m "First revision"

और इसे एक दिन कहते हैं!


docs.python.org/3/tutorial/modules.html#the-module-search-path का कहना है: "sys.path को इन स्थानों से आरंभ किया गया है: -इन निर्देशिका जिसमें इनपुट स्क्रिप्ट है"। मुझे लगता है कि यह सच नहीं है।

मैं ऐसा करने की प्रवृत्ति रखता हूं, विशेष रूप से .envrc ताकि direnv के साथ भी स्वचालित और अलग-थलग हो।
EdvardM

8

अजगर
3.4+ का उपयोग करके cx_freeze का उपयोग करना या IDLE का उपयोग करना। 😃

import sys
from pathlib import Path

sys.path.append(Path(__file__).parent / "lib")

पायथन 2 संगत: आयात पाथलिब आयात ओएस sys.path.append (os.path.dirname ( फ़ाइल ))
michael

5

आप python -mसंबंधित रूट dir से स्क्रिप्ट चला सकते हैं । और तर्क के रूप में "मॉड्यूल पथ" पास करें।

उदाहरण: $ python -m module.sub_module.main # Notice there is no '.py' at the end.


एक और उदाहरण:

$ tree  # Given this file structure
.
├── bar
   ├── __init__.py
   └── mod.py
└── foo
    ├── __init__.py
    └── main.py

$ cat foo/main.py
from bar.mod import print1
print1()

$ cat bar/mod.py
def print1():
    print('In bar/mod.py')

$ python foo/main.py  # This gives an error
Traceback (most recent call last):
  File "foo/main.py", line 1, in <module>
    from bar.mod import print1
ImportError: No module named bar.mod

$ python -m foo.main  # But this succeeds
In bar/mod.py

1
एम स्विच का उपयोग करना ऐसा करने का अनुशंसित तरीका है और
एसईएस

4

हर उत्तर के साथ एक समस्या है, जिसे संक्षेप में प्रस्तुत किया जा सकता है, "बस अपनी स्क्रिप्ट की शुरुआत में इस जादुई झुकाव को जोड़ें। देखें कि आप केवल एक पंक्ति या दो कोड के साथ क्या कर सकते हैं।" वे हर संभव स्थिति में काम नहीं करेंगे!

उदाहरण के लिए, इस तरह के एक जादुई झुकाव फ़ाइल का उपयोग करता है । दुर्भाग्य से, यदि आप cx_Freeze का उपयोग करके अपनी स्क्रिप्ट को पैकेज करते हैं या आप IDLE का उपयोग कर रहे हैं, तो इसका परिणाम अपवाद होगा।

इस तरह के एक और जादुई झुकाव os.getcwd () का उपयोग करता है। यह तभी काम करेगा जब आप अपनी स्क्रिप्ट को कमांड प्रॉम्प्ट से चला रहे हों और आपकी स्क्रिप्ट वाली डायरेक्टरी वर्तमान में काम करने वाली डायरेक्टरी हो (जो कि स्क्रिप्ट चलाने से पहले डायरेक्टरी में बदलने के लिए सीडी कमांड का उपयोग किया जाता है)। ऐ देवताओं! मुझे आशा है कि मुझे यह समझाने की ज़रूरत नहीं है कि अगर आपके पैथॉन स्क्रिप्ट पैठ में कहीं है तो यह काम नहीं करेगा और आपने इसे केवल अपनी स्क्रिप्ट फ़ाइल का नाम लिखकर चलाया।

सौभाग्य से, एक जादुई भस्म है जो मेरे द्वारा परीक्षण किए गए सभी मामलों में काम करेगा। दुर्भाग्य से, जादुई भस्म कोड की एक पंक्ति या दो से अधिक है।

import inspect
import os
import sys

# Add script directory to sys.path.
# This is complicated due to the fact that __file__ is not always defined.

def GetScriptDirectory():
    if hasattr(GetScriptDirectory, "dir"):
        return GetScriptDirectory.dir
    module_path = ""
    try:
        # The easy way. Just use __file__.
        # Unfortunately, __file__ is not available when cx_freeze is used or in IDLE.
        module_path = __file__
    except NameError:
        if len(sys.argv) > 0 and len(sys.argv[0]) > 0 and os.path.isabs(sys.argv[0]):
            module_path = sys.argv[0]
        else:
            module_path = os.path.abspath(inspect.getfile(GetScriptDirectory))
            if not os.path.exists(module_path):
                # If cx_freeze is used the value of the module_path variable at this point is in the following format.
                # {PathToExeFile}\{NameOfPythonSourceFile}. This makes it necessary to strip off the file name to get the correct
                # path.
                module_path = os.path.dirname(module_path)
    GetScriptDirectory.dir = os.path.dirname(module_path)
    return GetScriptDirectory.dir

sys.path.append(os.path.join(GetScriptDirectory(), "lib"))
print(GetScriptDirectory())
print(sys.path)

जैसा कि आप देख सकते हैं, यह कोई आसान काम नहीं है!


0

यह मेरे लिए सबसे अच्छा काम करता है। उपयोग:

os.path.abspath('')

मैक पर इसे कुछ इस तरह प्रिंट करना चाहिए:

'/Users/<your username>/<path_to_where_you_at>'

वर्तमान wd के लिए एब्स पथ प्राप्त करने के लिए, यह बेहतर है क्योंकि अब आप चाहें तो ऊपर जा सकते हैं, जैसे:

os.path.abspath('../')

और अब:

 '/Users/<your username>/'

इसलिए यदि आप utilsयहाँ से आयात करना चाहते हैं, तो आपको '/Users/<your username>/'
बस यही करना है:

import sys
sys.path.append(os.path.abspath('../'))

0

मुझे आपके उदाहरण में एक चरवाहा दिखाई दे रहा है। यदि आप अपनी बिन स्क्रिप्ट चला रहे हैं ./bin/foo.py, तो इसके बजाय python ./bin/foo.py, $PYTHONPATHचर को बदलने के लिए शेबंग का उपयोग करने का एक विकल्प है ।

हालांकि, आप सीधे चरवाहों में पर्यावरण चर नहीं बदल सकते हैं, इसलिए आपको एक छोटी सहायक स्क्रिप्ट की आवश्यकता होगी। इसे python.shअपने binफ़ोल्डर में रखें :

#!/usr/bin/env bash
export PYTHONPATH=$PWD/lib
exec "/usr/bin/python" "$@"

और फिर अपने ./bin/foo.pyहोने का चरवाहा बदलो#!bin/python.sh


0

जब हम टर्मिनल से पथ के साथ अजगर फ़ाइल को चलाने की कोशिश करते हैं।

import sys
#For file name
file_name=sys.argv[0]
#For first argument
dir= sys.argv[1]
print("File Name: {}, argument dir: {}".format(file_name, dir)

फ़ाइल (test.py) सहेजें।

रनिंग सिस्टम।

टर्मिनल खोलें और उस डायर को जाएं जहां फाइल सेव है। फिर लिखें

python test.py "/home/saiful/Desktop/bird.jpg"

हिट दर्ज करें

आउटपुट:

File Name: test, Argument dir: /home/saiful/Desktop/bird.jpg
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.