require#
טעינת קובץ מקור Perl בזמן ריצה, או דרישת גרסת Perl מינימלית.
ל־require שלוש צורות העושות דברים שונים למדי. עם מספר גרסה הוא טוען שהמפרש הרץ חדש מספיק. עם bareword הוא טוען מודול על־ידי המרת Foo::Bar ל־Foo/Bar.pm וחיפוש ב־@INC. עם מחרוזת זמן ריצה או $_ הוא טוען שם קובץ מילולית. כל השלוש הן פעולות זמן ריצה - בניגוד ל־use, שהוא require + import עטופים בבלוק BEGIN של זמן הידור.
תקציר#
require VERSION
require EXPR
require
מה מוחזר#
עבור צורת בדיקת הגרסה: 1 אם ה־Perl הרץ חדש מספיק; אחרת נזרקת חריגה (Perl vX.Y.Z required--this is only ...). אין מה לבדוק.
עבור צורות טעינת הקובץ: ערך האמת שמוחזר על־ידי ההצהרה האחרונה של הקובץ הנטען, או 1 אם הקובץ מפעיל את התכונה module_true (ברירת מחדל תחת use v5.38 ואילך). require שני של אותו נתיב מחזיר 1 בלי להריץ מחדש את הקובץ. כישלון זורק חריגה - או שגיאת הידור/זמן ריצה מהקובץ, Can't locate Foo/Bar.pm in @INC ..., או Foo/Bar.pm did not return true value.
יש לעטוף ב־eval כאשר רוצים לבדוק האם מודול ניתן לטעינה:
eval { require Some::Optional::Module };
if ($@) { ... } # module missing or broken
מצב גלובלי שהוא נוגע בו#
@INC- נתיב החיפוש עבור צורות bareword ושמות קבצים יחסיים. ערכים יכולים להיות מחרוזות ספריה, הפניות קוד, הפניות מערך, או עצמים מבורכים (ראו הוואי@INCלהלן).%INC- ממפה את שם הקובץ המבוקש (Foo/Bar.pm) לנתיב המוחלט שנטען.requireפונה אליו כדי להימנע מטעינה כפולה וקובע אותו בהצלחה. ערך שלundefמסמן קובץ שהידורו נכשל.$_- בשימוש כשם הקובץ כאשרrequireנקרא ללא ארגומנט.${^HOOK}{require__before}ו־${^HOOK}{require__after}- הפניות קוד אופציונליות הרצות סביב כלrequire, זמינות למעטפות מעקב והנמקה.
שלוש הצורות#
require VERSION - בדיקת Perl מינימלי#
VERSION הוא או v-string כגון v5.38.0 (מושווה מול $^V) או ליטרל מספרי כגון 5.038000 (מושווה מול $]). אם המפרש הרץ ישן יותר, require זורק.
require v5.38; # preferred
require 5.038; # numeric; same effect
require 5.038_000; # same; pre-5.6 syntax
זוהי בדיקת זמן ריצה. אם רוצים שהבדיקה תתרחש בזמן הידור (כך שהסקריפט לעולם לא ייפעל על Perl ישן), יש להשתמש ב־use VERSION במקום:
use v5.38; # compile-time equivalent
require EXPR כאשר EXPR הוא bareword - מודול לפי שם#
bareword מתפרש כשם מודול. require מחליף כל :: ב־/ ומצרף .pm, ואז מחפש ב־@INC:
require Foo::Bar; # looks for Foo/Bar.pm in @INC
צורה זו גם מבצעת autovivify ל־stash בזמן הידור - האש החבילה Foo::Bar:: קופץ לקיום גם אם הטעינה נכשלת מאוחר יותר. אין סמלים מיובאים; require רק טוען קוד.
לפני שמנסה את Foo/Bar.pm, require מחפש את Foo/Bar.pmc באותה ספריה ומעדיף אותו אם נמצא. ההוו של .pmc מאפשר לכלי בנייה לשלוח קבצים נלווים מהודרים־מראש לצד מקורות.
require EXPR כאשר EXPR הוא מחרוזת - קובץ לפי נתיב#
כל ביטוי שאינו bareword מטופל כשם קובץ מילולי. ללא תרגום ::, ללא צירוף .pm, ללא autovivification של stash:
require "Foo/Bar.pm"; # explicit .pm path
require "$config_dir/init.pl"; # arbitrary filename
my $class = 'Foo::Bar';
require $class; # ERROR: looks for file "Foo::Bar"
השורה האחרונה היא המלכודת הקלאסית: ברגע ששם המודול נמצא בסקלר, הוא מחרוזת, לא bareword. כדי לטעון מודול ששמו מחושב, יש לבצע את התרגום ידנית או לעבור דרך eval:
(my $file = "$class.pm") =~ s{::}{/}g;
require $file;
eval "require $class; 1" or die $@;
אם EXPR מושמט לחלוטין, $_ בשימוש.
שומר ה־%INC - קבצים נטענים נשארים טעונים#
לפני החיפוש ב־@INC, require פונה ל־%INC. אם שם הקובץ המבוקש נוכח ויש לו ערך אמת, require מחזיר 1 מיידית בלי לקרוא מחדש את הקובץ. אם הערך הוא undef, טעינה קודמת נכשלה ו־require זורק Compilation failed in require - Perl מסרב לנסות שוב קובץ שכבר התפוצץ פעם אחת במפרש זה.
זה אומר שקוד ברמה העליונה של מודול רץ בדיוק פעם אחת למפרש, לא משנה כמה מקומות require אותו. אתחול בגוף קובץ המודול הוא פעולה חד־פעמית; אין להסתמך על כך שהוא ירוץ עבור כל קריאת require בכל קורא.
הוו רשאי לקבוע את %INC בעצמו; אם לא, require רושם את ההוו כ״מקור״ של הטעינה.
מוסכמת ה־1;#
היסטורית כל קובץ הניתן לטעינה היה חייב להחזיר ערך אמת כביטוי האחרון שלו, אחרת require זרק filename did not return true value. הדרך הקנונית להבטיח זאת היא 1; מסיים:
package My::Thing;
# ... module code ...
1; # mandatory, pre-5.38
מ־Perl 5.38 ואילך, התכונה module_true - מופעלת כברירת מחדל תחת use v5.38 ואילך - גורמת לכל קובץ שעובר require להחזיר אמת באופן מובלע בהידור מוצלח. קבצים המצטרפים אינם צריכים יותר 1;. קבצים שלא, עדיין כן.
זה משפיע רק על יחידת ההידור שהפעילה את התכונה; מודולים legacy שנטענים על־ידי קורא מודרני עדיין צריכים את ה־1; שלהם.
כאשר הקובץ הנטען אכן מחזיר ערך ו־module_true כבוי, אותו ערך הוא מה ש־require מחזיר - אך רק בטעינה הראשונה. קריאות require עוקבות של אותו קובץ מחזירות 1 ממטמון ה־%INC. כדי ללכוד את ערך ההחזרה של קובץ באופן אמין, יש להשתמש ב־do:
my $config = do "config.pl"
or die "config.pl: ", $@ || $!;
הוואי @INC - הפניות קוד, הפניות מערך, ועצמים#
ערכים ב־@INC אינם חייבים להיות מחרוזות ספריה. הפניה השמורה ב־@INC נקראת הוו ומקבלת הזדמנות לספק את ה־require.
הפניה לתת־שגרה#
נקרא עם שני ארגומנטים: הפניית הקוד עצמה ושם הקובץ (Foo/Bar.pm). היא צריכה להחזיר או כלום (משמעות ״אינני יכול לטפל בזה; נסה את הערך הבא״) או עד ארבעה ערכים:
הפניה סקלרית לטקסט מקור הקודם לקובץ.
מטפל קובץ שממנו נקרא שאר המקור.
תת־שגרת גנרטור או מסנן (ראו
perldoc perlfuncלפרוטוקול המדויק).מצב אופציונלי המוחזר לגנרטור.
push @INC, sub {
my ($self, $filename) = @_;
return unless $filename eq 'Virtual/Module.pm';
open my $fh, '<', \"package Virtual::Module; 1;";
return $fh;
};
הפניית מערך#
האיבר הראשון הוא הפניית קוד או עצם כלעיל; השאר הוא מצב שההוו יכול לקרוא בכל קריאה. כשהאיבר הראשון הוא עצם עם מתודה INC או INCDIR, המתודה מקבלת את הפניית המערך כארגומנט השלישי שלה.
push @INC, [\&my_loader, $db_handle, $cache];
עצם מבורך#
אם לעצם יש מתודה INC או INCDIR, require קורא לאותה מתודה; אחרת, אם העצם הוא גם הפניית קוד, הוא מופעל כמו הפניית תת־שגרה פשוטה. מתודות INC חייבות להיות מוצהרות עם שמן המוסמך במלואו (sub Foo::INC { ... }), משום שהסמל הלא־מוסמך INC מקובע לחבילה main.
הוו רשאי לעדכן בחופשיות את %INC כדי לרשום את הנתיב שסיפק; אם לא, require שומר את הפניית ההוו עצמה.
require מול use#
use Foo::Bar qw(x y);
# is almost exactly:
BEGIN {
require Foo::Bar;
Foo::Bar->import(qw(x y));
}
היבט |
|
|
|---|---|---|
מתי הוא רץ | זמן הידור (בתוך | זמן ריצה |
קורא ל־ | כן | לא |
bareword | כן | כן, כאשר נקרא על bareword |
צורת בדיקת גרסה |
|
|
טוב עבור | תלויות קבועות | מודולים אופציונליים / קשורים מאוחר |
יש להישען על require כאשר המודול אופציונלי, נטען משם מחושב, או נטען רק בתוך ענף שעלול לעולם לא לרוץ. יש להישען על use עבור כל השאר.
דוגמאות#
גרסת Perl מינימלית בזמן ריצה:
require v5.38;
טעינת מודול bareword - מחפש ב־@INC, עושה autovivify ל־Data::Dumper:: בזמן הידור:
require Data::Dumper;
Data::Dumper->import;
print Data::Dumper::Dumper(\%ENV);
מודול אופציונלי - נסיגה חיננית כשחסר:
my $have_json = eval { require JSON::PP; 1 };
if ($have_json) {
print JSON::PP->new->encode($data);
}
טעינת מודול ששמו מחושב בזמן ריצה. יש להמיר לנתיב שם קובץ; require $class יחפש קובץ מילולי בשם Foo::Bar:
my $driver = $ENV{DB_DRIVER} // 'SQLite';
my $class = "DBD::$driver";
(my $file = "$class.pm") =~ s{::}{/}g;
require $file;
טעינת קטע הגדרה לפי שם נתיב, תוך שמירת ערך ההחזרה שלו - שימו לב ל־do, לא require, משום שאנחנו רוצים את הערך בכל קריאה:
my $config = do '/etc/myapp/config.pl'
or die "config load failed: ", $@ || $!;
התקנת הוו @INC המגיש מודול וירטואלי יחיד ממחרוזת בזיכרון:
unshift @INC, sub {
my ($self, $filename) = @_;
return unless $filename eq 'MyApp/Version.pm';
my $src = "package MyApp::Version; our \$VERSION = '1.23'; 1;";
open my $fh, '<', \$src;
$INC{$filename} = '(generated)';
return $fh;
};
require MyApp::Version;
מקרי קצה#
bareword מול מחרוזת:
require Foo::Barו־require "Foo::Bar"אינם זהים. צורת ה־bareword מתורגמת ל־Foo/Bar.pm; צורת המחרוזת מחפשת קובץ ששמו מילוליתFoo::Bar.שמות מחלקה מחושבים:
require $classכאשר$classמחזיק'Foo::Bar'מחפש קובץ בשםFoo::Bar, לאFoo/Bar.pm. יש לתרגם את השם בעצמכם, או להשתמש ב־eval "require $class"כאשר השם אמין.ללא ארגומנט:
require;משתמש ב־$_כשם הקובץ. נדיר בקוד מודרני; כמעט תמיד תאונה.ניסיונות הזדמנות שנייה אינם עובדים: אם
requireנכשל באמצע ההידור,%INCרושםundefעבור אותו שם קובץ.requireמאוחר יותר של אותו שם רואה את ה־undefוזורקCompilation failed in requireבלי להריץ מחדש את הקובץ. יש למחוק את הערך ב־%INCאם באמת רוצים לנסות שוב (זהו קצה חד; עדיף לתקן את הכישלון הבסיסי).הסרת ה־
.היחסי:.הוסר מ־@INCברירת המחדל ב־Perl 5.26. סקריפט שנהג למצוא אתFoo/Bar.pmלידו צריך כעת להוסיף את הספריה שלו במפורש (use FindBin; use lib $FindBin::Bin;).הצללת
.pmc: אםFoo/Bar.pmcקיים באותה ספריה כמוFoo/Bar.pm, ה־.pmcמנצח. קובצי.pmcמיושנים הם מלכודת קלאסית של ״למה העריכה שלי לא נכנסת לתוקף״.פרסור
require(EXPR):requireמפורסר כאופרטור אונרי בעל שם;require EXPR + 1משמעוrequire(EXPR + 1). יש להשתמש בסוגריים מפורשים כאשר הארגומנט הוא ביטוי לא־טריוויאלי.autovivification של stash:
require Foo::Barיוצר את ה־stash שלFoo::Bar::גם אם הקובץ חסר. בדיקותdefined &Foo::Bar::some_subבמורד הזרם עלולות לעבור את שלב ״החבילה קיימת״ אך להיכשל בשלב ״תת־השגרה קיימת״.מטפל קובץ מהוו חייב להיות אמיתי: מטפלי קובץ קשורים (tied) נדחים בשקט על־ידי פרוטוקול ההוו; הטיפול נופל מהקצה ו־
requireמדווח ״לא נמצא״. יש להשתמש ב־typeglob אמיתי.INCחייב להיות מוסמך במלואו במחלקות הוו:sub Foo::INC { ... }עובד;sub INC { ... }בתוךpackage Fooמתקיןmain::INCבגלל כלל חבילה מקובע.require()קשה לעטיפה: מודולים רבים בוחנים את מחסנית הקריאות כדי למצוא את הקורא שלהם. מעטפת שמוסיפה frame לעתים קרובות שוברת אותם. עדיף את הוואי${^HOOK}{require__before}/${^HOOK}{require__after}(נוספו ב־5.38) למעקב.
הבדלים מהמעלה־הזרם#
תאימות מלאה עם Perl 5.42 מהמעלה־הזרם.
ראו גם#
use-require+importבזמן הידור; הדרך הרגילה למשוך מודול שתלויים בו ללא תנאיdo- טעינת קובץ והחזרת ערכו בכל קריאה, ללא שמירת%INCבמטמון וללא כלל ״חייב להחזיר אמת״import- המתודה ש־useקורא לאחרrequire;requireלעולם אינו קורא לה בשבילכם@INC- נתיב חיפוש שאליו פונים עבור טעינות bareword ושמות קבצים יחסיים; מקבל מחרוזות ספריה, הפניות קוד, הפניות מערך, ועצמים כהוואי%INC- מטמון בעל ערך־אחד־לקובץ־טעון שגורם ל־requireלהיות אידמפוטנטי ורושם מהיכן הגיע כל מודולeval- לעטוף אתrequireכשמותר לטעינה להיכשל