Nhập mô-đun từ thư mục mẹ


625

Tôi đang chạy Python 2.5.

Đây là cây thư mục của tôi:

ptdraft/
  nib.py
  simulations/
    life/
      life.py

(Tôi cũng có __init__.pytrong mỗi thư mục, được bỏ qua ở đây để dễ đọc)

Làm cách nào để nhập nibmô-đun từ bên trong lifemô-đun? Tôi hy vọng có thể làm mà không cần mày mò với sys.path.

Lưu ý: Mô-đun chính đang chạy nằm trong ptdraftthư mục.


1
Cài đặt PYTHONPATH của bạn là gì?
S.Lott

2
Ross: Tôi đã nhìn ở đó. Tôi nên làm gì với nó? Tôi đã có một __init__.py. S.Lott: Tôi không biết cách kiểm tra ...
Ram Rachum

4
echo $ PYTHONPATH từ vỏ; hệ thống nhập khẩu; in sys.path từ bên trong Python. docs.python.org/tutorial/ trộm
S.Lott

@FlipMcF Google là một công cụ tìm kiếm sủi bọt, vì vậy thực tế là kết quả này khá cao đối với bạn không quan trọng. Điều quan trọng hơn nhiều là thực tế là công cụ tìm kiếm không sủi bọt, DuckDuckGo, cũng xếp hạng này rất cao.
ArtOfWarfare 17/05/2015

3
Tôi thực sự khuyên bạn nên bỏ qua tất cả sys.pathhoặc PYTHONPATHcâu trả lời và kiểm tra câu trả lời tuyệt vời của np8 . Vâng, đó là một bài đọc dài. Vâng, có vẻ như rất nhiều công việc. Nhưng đó là câu trả lời duy nhất thực sự giải quyết vấn đề một cách chính xác và sạch sẽ.
Aran-Fey

Câu trả lời:


118

Có vẻ như vấn đề không liên quan đến mô-đun nằm trong thư mục mẹ hoặc bất cứ điều gì tương tự.

Bạn cần thêm thư mục chứa ptdraftvào PYTHONPATH

Bạn nói rằng import nibđã làm việc với bạn, điều đó có thể có nghĩa là bạn đã thêm ptdraftchính nó (không phải cha mẹ của nó) vào PYTHONPATH.


15
Phải thêm mọi thứ vào pythonpath không phải là một giải pháp tốt nếu bạn đang làm việc với rất nhiều gói sẽ không bao giờ được sử dụng lại.
Jason Cheng

@JasonCheng: Vậy tại sao họ là gói ?
Davis Herring

7
Đối với tôi câu trả lời này đã làm việc ra. Tuy nhiên, để làm cho nó rõ ràng hơn, thủ tục là import sysvà sau đósys.path.append("..\<parent_folder>")
BCJuan

603

Bạn có thể sử dụng nhập tương đối (python> = 2.5):

from ... import nib

(Có gì mới trong Python 2.5) PEP 328: Nhập khẩu tuyệt đối và tương đối

EDIT : thêm một dấu chấm '.' đi lên hai gói


177
ValueError: Attempted relative import in non-package
endolith

18
@endolith: Bạn phải ở trong một gói, tức là bạn phải có tệp init .py.
kirbyfan64sos

31
Đã cố nhập tương đối ngoài gói toplevel
Người dùng

29
Để chính xác hơn nữa, bạn cần một __init__.pytập tin.
kara deniz

17
Xem thêm câu trả lời sau, vì thêm __init__.pykhông phải là điều duy nhất bạn phải làm: stackoverflow.com/questions/11536764/ Kẻ
Nông dân Ben

286

Nhập khẩu tương đối (như trong from .. import mymodule) chỉ hoạt động trong một gói. Để nhập 'mymodule' trong thư mục mẹ của mô-đun hiện tại của bạn:

import os,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir) 

import mymodule

chỉnh sửa : __file__thuộc tính không phải luôn luôn được đưa ra. Thay vì sử dụng, os.path.abspath(__file__)bây giờ tôi đề nghị sử dụng mô-đun kiểm tra để lấy tên tệp (và đường dẫn) của tệp hiện tại


97
một cái gì đó ngắn hơn một chút:sys.path.insert(1, os.path.join(sys.path[0], '..'))
JHolta

8
Bất kỳ lý do để tránh sys.path.append () thay vì chèn?
Tyler

2
@Tyler - Có thể có vấn đề nếu ở một nơi khác sau đó parentdir, nhưng trong một trong những đường dẫn đã được chỉ định trong sys.pathđó, có một mô-đun khác có tên 'mymodule'. Chèn parentdirphần tử đầu tiên của sys.pathdanh sách đảm bảo rằng mô-đun từ parentdirsẽ được nhập thay thế.
Remi

5
@JHolta Nếu bạn không xử lý các gói, thì đó là giải pháp tốt nhất.
Jonathon Reinhart

5
@JHolta ý tưởng tuyệt vời. sys.path.insert(1, os.path.realpath(os.path.pardir))làm việc quá
SpeedCoder5

177

Tôi cũng đăng một câu trả lời tương tự cho câu hỏi liên quan đến hàng nhập khẩu từ các gói anh chị em. Bạn có thể thấy nó ở đây .

Giải pháp không sys.pathhack

Tóm lược

  • Gói mã vào một thư mục (ví dụ packaged_stuff)
  • Sử dụng tạo setup.pytập lệnh trong đó bạn sử dụng setuptools.setup () .
  • Pip cài đặt gói ở trạng thái có thể chỉnh sửa với pip install -e <myproject_folder>
  • Nhập khẩu bằng cách sử dụng from packaged_stuff.modulename import function_name

Thiết lập

Tôi giả sử cấu trúc thư mục giống như trong câu hỏi

.
└── ptdraft
    ├── __init__.py
    ├── nib.py
    └── simulations
        ├── __init__.py
        └── life
            ├── __init__.py
            └── life.py

Tôi gọi .thư mục gốc, và trong trường hợp của tôi, nó nằm ở C:\tmp\test_imports.

Các bước

1) Thêm a setup.pyvào thư mục gốc

Nội dung của setup.pycó thể chỉ đơn giản là

from setuptools import setup, find_packages

setup(name='myproject', version='1.0', packages=find_packages())

Về cơ bản "bất kỳ" setup.pysẽ làm việc. Đây chỉ là một ví dụ làm việc tối thiểu.

2) Sử dụng môi trường ảo

Nếu bạn quen thuộc với môi trường ảo, hãy kích hoạt một và bỏ qua bước tiếp theo. Việc sử dụng môi trường ảo không hoàn toàn bắt buộc, nhưng chúng thực sự sẽ giúp bạn trong thời gian dài (khi bạn có hơn 1 dự án đang diễn ra ..). Các bước cơ bản nhất là (chạy trong thư mục gốc)

  • Tạo env ảo
    • python -m venv venv
  • Kích hoạt env ảo
    • . /venv/bin/activate(Linux) hoặc ./venv/Scripts/activate(Thắng)

Để tìm hiểu thêm về điều này, chỉ cần Google tìm ra "hướng dẫn python virtualenv" hoặc tương tự. Bạn có thể không bao giờ cần bất kỳ lệnh nào khác ngoài việc tạo, kích hoạt và hủy kích hoạt.

Khi bạn đã tạo và kích hoạt một môi trường ảo, bảng điều khiển của bạn sẽ đặt tên của môi trường ảo trong ngoặc đơn

PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>

3) Pip cài đặt dự án của bạn ở trạng thái có thể chỉnh sửa

Cài đặt gói cấp cao nhất của bạn myprojectbằng cách sử dụng pip. Mẹo nhỏ là sử dụng -ecờ khi thực hiện cài đặt. Bằng cách này, nó được cài đặt ở trạng thái có thể chỉnh sửa và tất cả các chỉnh sửa được thực hiện cho các tệp .py sẽ được tự động đưa vào gói đã cài đặt.

Trong thư mục gốc, hãy chạy

pip install -e . (lưu ý dấu chấm, nó là viết tắt của "thư mục hiện tại")

Bạn cũng có thể thấy rằng nó được cài đặt bằng cách sử dụng pip freeze

(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
  Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0

4) Nhập bằng cách trả trước mainfoldercho mỗi lần nhập

Trong ví dụ này, mainfoldersẽ là ptdraft. Điều này có lợi thế là bạn sẽ không gặp phải xung đột tên với các tên mô-đun khác (từ thư viện tiêu chuẩn python hoặc mô-đun bên thứ 3).


Cách sử dụng ví dụ

nib.py

def function_from_nib():
    print('I am the return value from function_from_nib!')

cuộc sống

from ptdraft.nib import function_from_nib

if __name__ == '__main__':
    function_from_nib()

Chạy life.py

(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!

1
Tại sao điều này làm việc? Có phải nó đang thay đổi PYTHONPATH đằng sau hậu trường bằng cách nào đó?
Homero Esmeraldo

2
Ngoài ra, tại sao điều này tốt hơn hoặc thanh lịch hơn so với sử dụng phương pháp sys.path?
Homero Esmeraldo

5
@HomeroBarrocasSEsmeraldo Câu hỏi hay. PYTHONPATH env var không được chạm tới. Điều này cài đặt vào các gói trang web , đã có sẵn sys.pathvà nơi mã thường được cài đặt bởi người dùng cuối. Điều đó tốt hơn so với sys.pathhack (và bạn có thể bao gồm sử dụng PYTHONPATH trong danh mục hack đường dẫn đó) bởi vì điều đó có nghĩa là mã trong quá trình phát triển sẽ hành xử giống như bạn đối với người dùng khác. Ngược lại, khi sử dụng sửa đổi đường dẫn, báo cáo nhập sẽ được giải quyết theo một cách khác.
wim

5
Đây là giải pháp tốt nhất mà tôi đã đọc. Điều này tạo ra một liên kết đến thư mục hiện tại của bạn để tất cả các cập nhật cho mã được phản ánh trực tiếp vào thư mục làm việc của bạn. Trong trường hợp bạn cần xóa mục nhập này, hãy xóa thủ công tệp trứng và xóa mục nhập khỏi cài đặt dễ dàng trong các gói dist (gói trang web nếu bạn sử dụng pip).
Rakshit Kothari

2
Tại sao làm đau đầu nhập khẩu trăn thậm chí còn phức tạp hơn? Chúng ta phải viết một tập tin thiết lập, một env ảo, một cài đặt pip? Chúa ơi!
Emerson Xu

68

Bạn có thể sử dụng đường dẫn tùy thuộc HĐH trong "đường dẫn tìm kiếm mô-đun" được liệt kê trong sys.path . Vì vậy, bạn có thể dễ dàng thêm thư mục cha mẹ như sau

import sys
sys.path.insert(0,'..')

Nếu bạn muốn thêm thư mục cha-mẹ,

sys.path.insert(0,'../..')

Điều này hoạt động cả trong python 2 và 3.


6
Điều này liên quan đến thư mục hiện tại , thậm chí không nhất thiết là thư mục chứa tập lệnh chính.
Davis Herring

57

Nếu việc thêm thư mục mô-đun của bạn vào PYTHONPATH không hoạt động, Bạn có thể sửa đổi danh sách sys.path trong chương trình của mình nơi trình thông dịch Python tìm kiếm các mô-đun để nhập, tài liệu python nói:

Khi một mô-đun có tên là thư rác được nhập, đầu tiên trình thông dịch sẽ tìm kiếm mô-đun tích hợp có tên đó. Nếu không tìm thấy, nó sẽ tìm kiếm một tệp có tên spam.txt trong danh sách các thư mục được cung cấp bởi biến sys.path. sys.path được khởi tạo từ các vị trí này:

  • thư mục chứa tập lệnh đầu vào (hoặc thư mục hiện tại).
  • PYTHONPATH (danh sách các tên thư mục, có cùng cú pháp với biến shell PATH).
  • mặc định phụ thuộc cài đặt.

Sau khi khởi tạo, các chương trình Python có thể sửa đổi sys.path . Thư mục chứa tập lệnh đang chạy được đặt ở đầu đường dẫn tìm kiếm, phía trước đường dẫn thư viện chuẩn. Điều này có nghĩa là các tập lệnh trong thư mục đó sẽ được tải thay vì các mô đun cùng tên trong thư mục thư viện. Đây là một lỗi trừ khi có ý định thay thế.

Biết điều này, bạn có thể làm như sau trong chương trình của bạn:

import sys
# Add the ptdraft folder path to the sys.path list
sys.path.append('/path/to/ptdraft/')

# Now you can import your module
from ptdraft import nib
# Or just
import ptdraft

6
Câu trả lời của bạn là tốt, nhưng có thể không phải lúc nào cũng hoạt động và không phải là rất di động. Nếu chương trình được chuyển đến một vị trí mới, /path/to/ptdraftsẽ phải chỉnh sửa. Có những giải pháp xử lý thư mục hiện tại của tệp và nhập nó từ thư mục mẹ theo cách đó.
Edward

@Edward những kỹ thuật đó là gì?
Shuklaswag

1
@Shuklaswag chẳng hạn, câu trả lời stackoverflow.com/questions/714063/ ,.
Edward

50

Không biết nhiều về python 2.
Trong python 3, thư mục mẹ có thể được thêm vào như sau:

import sys 
sys.path.append('..')

... và sau đó người ta có thể nhập các mô-đun từ nó


13
Điều này chỉ hoạt động nếu thư mục làm việc hiện tại của bạn là như vậy '..'dẫn đến thư mục với mô-đun được đề cập.
dùng5359531

31

Đây là một câu trả lời đơn giản để bạn có thể thấy nó hoạt động như thế nào, nhỏ và đa nền tảng.
Nó chỉ sử dụng những built-in module ( os, sysinspect) vì vậy nên làm việc
trên bất kỳ hệ điều hành (OS) vì Python được thiết kế cho điều đó.

Mã ngắn hơn để trả lời - ít dòng và biến hơn

from inspect import getsourcefile
import os.path as path, sys
current_dir = path.dirname(path.abspath(getsourcefile(lambda:0)))
sys.path.insert(0, current_dir[:current_dir.rfind(path.sep)])
import my_module  # Replace "my_module" here with the module name.
sys.path.pop(0)

Đối với ít dòng hơn mức này, thay thế dòng thứ hai bằng import os.path as path, sys, inspect,
thêm inspect.vào đầu getsourcefile(dòng 3) và xóa dòng đầu tiên.
- tuy nhiên, điều này nhập tất cả các mô-đun để có thể cần thêm thời gian, bộ nhớ và tài nguyên.

Mã cho câu trả lời của tôi ( phiên bản dài hơn )

from inspect import getsourcefile
import os.path
import sys

current_path = os.path.abspath(getsourcefile(lambda:0))
current_dir = os.path.dirname(current_path)
parent_dir = current_dir[:current_dir.rfind(os.path.sep)]

sys.path.insert(0, parent_dir)

import my_module  # Replace "my_module" here with the module name.

Nó sử dụng một ví dụ từ câu trả lời Stack Overflow Làm thế nào để tôi có được đường dẫn của
tệp được thực thi hiện tại trong Python?
để tìm nguồn (tên tệp) của mã đang chạy bằng công cụ tích hợp.

from inspect import getsourcefile  
from os.path import abspath  

Tiếp theo, bất cứ nơi nào bạn muốn tìm tệp nguồn từ bạn chỉ cần sử dụng:

abspath(getsourcefile(lambda:0))

Mã của tôi thêm một đường dẫn tập tin để sys.path, những trăn danh sách đường
vì điều này cho phép Python để module nhập khẩu từ thư mục đó.

Sau khi nhập một mô-đun trong mã, bạn nên chạy sys.path.pop(0)trên một dòng mới
khi thư mục được thêm vào đó có một mô-đun có cùng tên với một mô-đun khác được nhập
sau này trong chương trình. Bạn cần xóa mục danh sách được thêm trước khi nhập, không phải các đường dẫn khác.
Nếu chương trình của bạn không nhập các mô-đun khác, sẽ không an toàn khi xóa đường dẫn tệp vì
sau khi chương trình kết thúc (hoặc khởi động lại trình bao Python), mọi chỉnh sửa được thực hiện sẽ sys.pathbiến mất.

Ghi chú về một biến tên tệp

Câu trả lời của tôi không sử dụng __file__biến để lấy đường dẫn tệp / tên tệp của
mã đang chạy vì người dùng ở đây thường mô tả nó là không đáng tin cậy . Bạn không nên sử dụng nó
để nhập các mô-đun từ thư mục mẹ trong các chương trình được người khác sử dụng.

Một số ví dụ mà nó không hoạt động (trích dẫn từ này câu hỏi Stack Overflow):

• nó không thể được tìm thấy trên một số nền tảng • đôi khi nó không phải là đường dẫn tệp đầy đủ

  • py2exekhông có __file__thuộc tính, nhưng có một cách giải quyết
  • Khi bạn chạy từ IDLE execute()mà không có __file__thuộc tính
  • OS X 10.6 nơi tôi nhận được NameError: global name '__file__' is not defined

1
Tôi đã làm điều này và loại bỏ mục nhập đường dẫn mới sys.path.pop(0)ngay lập tức sau khi nhập mô-đun mong muốn. Tuy nhiên, nhập khẩu tiếp theo vẫn đi đến địa điểm đó. Ví dụ, tôi có app/config, app/toolsapp/submodule/config. Từ submodule, tôi chèn app/để nhập tools, sau đó loại bỏ app/và cố gắng nhập config, nhưng tôi nhận được app/configthay vì app/submodule/config.
dùng5359531

Tôi đã tìm ra rằng một trong những toolshàng nhập khẩu cũng được nhập configtừ thư mục gốc. Vì vậy, sau đó khi tôi cố gắng làm sys.path.pop(0); import configbên trong submodule, mong muốn có được app/submodule/config, tôi thực sự đã nhận được app/config. Rõ ràng Python trả về một phiên bản được lưu trong bộ nhớ cache của một mô-đun có cùng tên thay vì thực sự kiểm tra sys.pathmô-đun khớp với tên đó. sys.pathtrong trường hợp này đã được thay đổi chính xác, Python chỉ không kiểm tra nó do mô-đun cùng tên đã được tải.
dùng5359531

Tôi nghĩ rằng đây là tài liệu tham khảo chính xác cho vấn đề tôi đã: docs.python.org/3/reference/import.html#the-module-cache
user5359531

Một số thông tin hữu ích từ 5.3.1. Bộ đệm mô-đun trên trang tài liệu : Trong quá trình nhập, tên mô-đun được tra cứu trong sys.modules ... sys.modules có thể ghi. Xóa khóa sẽ làm mất hiệu lực mục nhập bộ đệm cho mô-đun được đặt tên, khiến Python phải tìm kiếm lại lần nhập tiếp theo. ... Hãy coi chừng, như thể bạn giữ một tham chiếu đến đối tượng mô-đun, làm mất hiệu lực bộ đệm của nó sau đó nhập lại, hai đối tượng sẽ khác nhau. Ngược lại, importlib.reload()sẽ sử dụng lại và xác định lại nội dung mô-đun ...
Edward

Thậm chí ngắn hơn : os.path.realpath(getsourcefile(lambda:0) + "/../.."). Sẽ nhận được tệp nguồn hiện tại được nối với hai biểu tượng thư mục cha. Tôi đã không sử dụng os.path.sepnhư getsourcefiletrả về một chuỗi sử dụng /ngay cả trên Windows. realpathsẽ đảm nhiệm việc bật ra hai mục nhập thư mục từ đường dẫn đầy đủ (trong trường hợp này là tên tệp và sau đó là thư mục hiện tại) cung cấp thư mục mẹ.
Coburn

28

Đây là giải pháp chung hơn bao gồm thư mục mẹ vào sys.path (hoạt động với tôi):

import os.path, sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))

import os, sys\n sys.path.insert(0,os.path.pardir) điều tương tự, nhưng sắp xếp :) (không có nguồn cấp dữ liệu trong nhận xét)
Anti Veeranna

@antiveeranna, nếu bạn sử dụng, os.path.pardirbạn sẽ không nhận được sự đồng cảm của cha mẹ, chỉ là đường dẫn tương đối từ nơi bạn đang gọisys.path.insert()
alvas

1
Câu trả lời này sử dụng __file__biến có thể không đáng tin cậy (không phải luôn luôn là đường dẫn tệp đầy đủ, không hoạt động trên mọi hệ điều hành, v.v.) như người dùng StackOverflow thường đề cập. Thay đổi câu trả lời để không bao gồm nó sẽ gây ra ít vấn đề hơn và tương thích chéo hơn. Để biết thêm thông tin, xem stackoverflow.com/a/33532002/3787376 .
Edward

23

Tôi đã tìm thấy cách sau đây để nhập gói từ thư mục mẹ của tập lệnh. Trong ví dụ này, tôi muốn nhập khẩu chức năng trong env.pytừ app.dbgói.

.
└── my_application
    └── alembic
        └── env.py
    └── app
        ├── __init__.py
        └── db
import os
import sys
currentdir = os.path.dirname(os.path.realpath(__file__))
parentdir = os.path.dirname(currentdir)
sys.path.append(parentdir)

Vì vậy, một lớp lót đẹp:sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
juzzlin

Sửa đổi sys.pathtất cả thường là một ý tưởng tồi. Bạn cần một số cách ( ví dụ , PYTHONPATH) để thư viện của bạn có thể truy cập được vào mã khác (nếu không nó không thực sự là một thư viện); chỉ cần sử dụng tất cả các thời gian!
Davis Herring

14

Các giải pháp nêu trên cũng tốt. Một giải pháp khác cho vấn đề này là

Nếu bạn muốn nhập bất cứ thứ gì từ thư mục cấp cao nhất. Sau đó,

from ...module_name import *

Ngoài ra, nếu bạn muốn nhập bất kỳ mô-đun nào từ thư mục mẹ. Sau đó,

from ..module_name import *

Ngoài ra, nếu bạn muốn nhập bất kỳ mô-đun nào từ thư mục mẹ. Sau đó,

from ...module_name.another_module import *

Bằng cách này bạn có thể nhập bất kỳ phương thức cụ thể nào nếu bạn muốn.


6
Điều này có vẻ giống như nó phải vậy, nhưng vì một số lý do, điều này không hoạt động theo cách tương tự như các bản sys.path.appendhack ở trên và tôi không thể nhập lib của mình như thế này. Đây là điều đầu tiên tôi cố gắng làm trước khi bắt đầu google :) Ok, nó là thế nàyValueError: attempted relative import beyond top-level package
juzzlin

10

Đối với tôi, oneliner ngắn nhất và yêu thích của tôi để truy cập vào thư mục mẹ là:

sys.path.append(os.path.dirname(os.getcwd()))

hoặc là:

sys.path.insert(1, os.path.dirname(os.getcwd()))

os.getcwd () trả về tên của thư mục làm việc hiện tại, os.path.dirname (thư mục_name) trả về tên thư mục cho tên đã truyền.

Trên thực tế, theo tôi, kiến ​​trúc dự án Python nên được thực hiện theo cách mà không một mô-đun nào từ thư mục con sẽ sử dụng bất kỳ mô-đun nào từ thư mục mẹ. Nếu một cái gì đó như thế này xảy ra, nó đáng để suy nghĩ lại về cây dự án.

Một cách khác là thêm thư mục cha vào biến môi trường hệ thống PYTHONPATH.


2
+1 để đề cập đến khả năng phải cơ cấu lại dự án (trái ngược với việc ném một vụ hack vào vấn đề)
semore_1267

cái này không có được cha mẹ, nó có được hiện tại
Ricky Levi

9

Trong một máy tính xách tay Jupyter

Miễn là bạn đang làm việc trong Notebook Jupyter, giải pháp ngắn này có thể hữu ích:

%cd ..
import nib

Nó hoạt động ngay cả khi không có __init__.pytập tin.

Tôi đã thử nghiệm nó với Anaconda3 trên Linux và Windows 7.


2
Sẽ không có ý nghĩa để thêm %cd -sau khi nhập, vì vậy thư mục hiện tại của máy tính xách tay không thay đổi.
Dror


5

Khi không ở trong môi trường gói với __init__.pycác tệp, thư viện pathlib (bao gồm> = Python 3.4) làm cho nó rất ngắn gọn và trực quan để nối đường dẫn của thư mục mẹ vào PYTHONPATH:

import sys
from pathlib import Path
sys.path.append(str(Path('.').absolute().parent))

Có thể sử dụng init .py để tránh vấn đề này không?
Nhân tạo thông minh

4

cùng một kiểu như câu trả lời trước đây - nhưng trong ít dòng hơn: P

import os,sys
parentdir = os.path.dirname(__file__)
sys.path.insert(0,parentdir)

tập tin trả về vị trí bạn đang làm việc


Đối với tôi tập tin là tên tệp mà không có đường dẫn đi kèm. Tôi chạy nó bằng cách sử dụng "ipy filename.py".
Curtis Yallop

Xin chào @CurtisYallop trong ví dụ trên, chúng tôi đang thêm thư mục chứa tệp [mà chúng tôi hiện đang ở] rằng tệp python đang ở. Cuộc gọi os.path.dirname với tên tệp sẽ trả về đường dẫn của tệp và chúng tôi đang thêm THAT vào đường dẫn chứ không phải tệp rõ ràng - HTH's :-)
YFP

Bạn đang giả sử rằng __file__ luôn chứa đường dẫn cộng với tệp. Đôi khi nó chỉ chứa tên tệp mà không có đường dẫn.
Curtis Yallop

@CurtisYallop - hoàn toàn không phải thưa ngài, tôi giả sử tệp là tên tệp và tôi đang sử dụng os.path.dirname () để lấy đường dẫn cho tệp. Bạn đã có một ví dụ về điều này không làm việc? Tôi rất thích các bước để tái sản xuất
YFP

1
@CurtisYallop - Không, tôi không phải! Tôi đang nói rằng: print / _ / file / _ / sẽ cung cấp cho bạn tên tệp trong ví dụ của bạn ở trên "file.py" - Sau đó tôi nói rằng bạn có thể sử dụng os.path.dirname () để lấy đường dẫn đầy đủ từ đó . Nếu bạn đang gọi từ một vị trí kỳ lạ và bạn muốn mối quan hệ đó thì bạn có thể dễ dàng tìm thấy thư mục làm việc của mình thông qua mô-đun os - Jeez!
YFP

1

Làm việc với các thư viện. Tạo một thư viện có tên là nib, cài đặt nó bằng setup.py, để nó nằm trong các gói trang web và các vấn đề của bạn đã được giải quyết. Bạn không phải nhét mọi thứ bạn làm vào một gói. Phá vỡ nó thành từng mảnh.


1
Ý tưởng của bạn là tốt nhưng một số người có thể muốn đóng gói mô-đun của họ bằng mã của họ - có lẽ để làm cho nó di động và không yêu cầu đặt mô-đun của họ site-packagesmỗi khi họ chạy nó trên một máy tính khác.
Edward

0

Trong hệ thống Linux, bạn có thể tạo một liên kết mềm từ thư mục "cuộc sống" đến tệp nib.py. Sau đó, bạn có thể chỉ cần nhập nó như sau:

import nib
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.