Impor paket python dari direktori lokal ke interpreter

87

Saya mengembangkan / menguji paket di direktori lokal saya. Saya ingin mengimpornya di interpreter (v2.5), tetapi sys.path tidak menyertakan direktori saat ini. Sekarang saya mengetik sys.path.insert(0,'.'). Apakah ada cara yang lebih baik?

Juga,

from . import mypackage

gagal dengan kesalahan ini:

ValueError: Attempted relative import in non-package
projectshave
sumber
Dimana Anda membaca itu "." adalah modul Python?
S. Lotot
16
@ Lott: Ini adalah jalur impor relatif yang dijelaskan di sini: docs.python.org/reference/…
projectshave
1
Anda mungkin ingin melihat panduan definitif ini chrisyeh96.github.io/2017/08/08/…
Kevin Zhu

Jawaban:

46

Anda dapat menggunakan impor relatif hanya dari dalam modul yang pada gilirannya diimpor sebagai bagian dari sebuah paket - skrip atau penerjemah interaktif Anda tidak, jadi tentu saja from . import(yang berarti "impor dari paket yang sama tempat saya mengimpor dari") tidak tidak bekerja. import mypackageakan baik-baik saja setelah Anda memastikan direktori induk dari mypackagedalam sys.path(bagaimana Anda berhasil mendapatkan direktori Anda saat jauh dari sys.pathsaya tidak tahu -? apakah Anda memiliki sesuatu yang aneh di site.py, atau ...)

Untuk mengembalikan direktori Anda saat ini ke sys.pathsana sebenarnya tidak ada cara yang lebih baik daripada meletakkannya di sana.

Alex Martelli
sumber
Python 2.5 untuk Ubuntu 8.10 tidak memiliki direktori saat ini (string kosong) di sys.path untuk interpreter. Saya tidak mengubah apa pun, jadi entah bagaimana dikirim dengan cara itu. Saya baru saja menginstal 3.0 dan sys.path DOES have '' di sys.path.
projectshave
@projectshave, OK, Ubuntu pasti punya alasannya! Saya belum menyadarinya di 8.04 (yang saat ini kami gunakan di tempat kerja) tetapi mungkin saya kurang memperhatikan.
Alex Martelli
1
Saya salah sebagian. Python yang dipanggil dari shell memiliki direktori saat ini di sys.path. Python yang dipanggil dari Emacs tidak memiliki direktori saat ini. Aneh.
projectshave
1
Ah well, kalau begitu Emacs-lah yang punya alasan berbeda dengan Ubuntu (sebagai pengguna vim, saya tidak begitu tahu ;-). Anda dapat memasukkan '.' di sys.path Anda jika tidak ada tentu saja.
Alex Martelli
@Alex Martelli: Terima kasih banyak! Saya telah mencari dan mencari solusi mengapa add-on saya (untuk Anki) membutuhkan pernyataan impor yang berbeda saat dijalankan 'secara lokal' sebagai skrip. Ketika saya malah menambahkan metode local_launch () dan mengimpor / meluncurkan semuanya dari skrip di luar folder paket, itu bekerja seperti pesona!
Jon Coombs
18

Lihat dokumentasi untuk sys.path:

http://docs.python.org/library/sys.html#sys.path

Kutipan:

Jika direktori skrip tidak tersedia (misalnya jika penerjemah dipanggil secara interaktif atau jika skrip dibaca dari input standar), jalur [0] adalah string kosong, yang mengarahkan Python untuk mencari modul di direktori saat ini terlebih dahulu.

Jadi, tidak perlu menggunakan sys.path jika Anda memulai interpreter python dari direktori yang berisi modul Anda.

Juga, untuk mengimpor paket Anda, cukup lakukan:

import mypackage

Karena direktori yang berisi paket sudah ada di sys.path, ini akan berfungsi dengan baik.

SpoonMeiser
sumber
1
Ini akan gagal jika nama file serupa ada di tempat lain di env yang berfungsi.
JAR.JAR. Kacang
@ JAR.JAR.beans direktori kerja saat ini harus menjadi hal pertama sys.pathsehingga file di sana harus ditemukan sebelum file di tempat lain di lingkungan kerja.
SpoonMeiser
3
Poin yang bagus. Artinya, jika kita menjalankan file dari direktori lokal. Dalam kasus ini folder lain, dan dalam kasus perubahan sys.path diperlukan - itu berarti sys.path.insert(0, new_path)daripada sys.path.append(new_path).
JAR.JAR. Kacang
15

Jika Anda ingin menjalankan skrip python yang tidak dimodifikasi sehingga mengimpor pustaka dari direktori lokal tertentu, Anda dapat menyetel PYTHONPATHvariabel lingkungan - misalnya di bash:

export PYTHONPATH=/home/user/my_libs
python myscript.py

Jika Anda hanya ingin mengimpor dari direktori kerja saat ini, gunakan .notasi:

export PYTHONPATH=.
python myscript.py
Pierz
sumber
Mengekspor PYTHONPATH mencakup pemrograman di luar python (misalnya di bash). Selain itu, di docs.python.org/3/using/cmdline.html dengan jelas dinyatakan bahwa " jalur pencarian default bergantung pada instalasi ".
ilias iliadis
13

Buat tetap sederhana:

 try:
     from . import mymodule     # "myapp" case
 except:
     import mymodule            # "__main__" case
Guido U. Draheim
sumber
7
Saya suka solusi ini, ini yang paling sederhana. Satu-satunya pertanyaan yang tersisa adalah mengapa aturan "satu-satunya cara untuk melakukannya" dianggap opsional saat menerapkan impor ... Serius, ada sekitar 15 cara untuk mendeklarasikan dan mengatur paket, yang semuanya memiliki kekurangan
Léo Germond
5

Cara sederhana untuk membuatnya berfungsi adalah dengan menjalankan skrip Anda dari direktori induk menggunakan -mflag python , mis python -m packagename.scriptname. Jelas dalam situasi ini Anda memerlukan __init__.pyfile untuk mengubah direktori Anda menjadi sebuah paket.

bradley.ayers
sumber
5

Di dalam sebuah paket jika ada setup.py , maka lebih baik menginstalnya

pip install -e .
Nagashayan
sumber
3

Penggunaan sys.pathharus sudah menyertakan direktori saat ini.

Mencoba:

import .

atau:

from . import sth

namun ini mungkin bukan praktik yang baik, jadi mengapa tidak menggunakan saja:

import mypackage
sunqiang
sumber
5
Masalah dengan <import mypackage> adalah bahwa ia akan memuat paket dari global python env, itu mungkin memuat paket / file dari folder lokal, tetapi bisa juga memuat beberapa mypackge acak lain yang ada di env kerja.
JAR.JAR. Kacang
3

Agak terlambat ke pesta, tapi inilah yang berhasil bagi saya:

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

Rupanya, jika ada string kosong, Python tahu bahwa itu harus dicari di direktori saat ini. Saya tidak memiliki string kosong sys.path, yang menyebabkan kesalahan ini.

maninthecomputer
sumber
1

Saya biasa pathlibmenambahkan direktori modul saya ke jalur sistem saya karena saya ingin menghindari menginstal modul sebagai paket dan tanggapan @maninthecomputer tidak berfungsi untuk saya

import sys
from pathlib import Path

cwd = str(Path(__file__).parent)
sys.path.insert(0, cwd)
from my_module import my_function
rdmolony.dll
sumber