Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Пакеты, проверить существование пакета. 
:(
    Опции темы
Logo
Дата 21.2.2010, 06:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Как проверить, существует ли определенный пакет в программе? Как удалить пакет и все его переменные?
PM MAIL   Вверх
sir_nuf_nuf
Дата 21.2.2010, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 920
Регистрация: 6.1.2008

Репутация: 14
Всего: 31



проверить загруженному пакету соответсвует соответвует таблица символов.
таблица символов - это обычный хэш с именем совпадающим с пакетом.

Например если пакет называется Data::Dumper, то его таблица символов %Data::Dumper::  (двоеточия в конце обязательны).

Сама таблица символов пакета (т.е. хэш)  является записью в таблице символов основного пакета (main).

Поэтому проверить наличие пакета можно так:

Код

use warnings;
use strict;

sub check_pkg ($) {
    my $pkg = shift || return;
    $pkg =~ s/(::)?$/::/;
    my ($base, $tail) = ($pkg =~ /^(.+::)?(.+::)$/);
    no strict 'refs';
    return defined ${$base || 'main::'}{$tail};
}

print check_pkg($ARGV[0]) ? 'yes' : 'no';



А зачем вам понадобилось удалять пакет ?  
Память вам освободить не удастся.
Можно конечо удалить те переменные которые вы импортировали в свой пакет.

Это сообщение отредактировал(а) sir_nuf_nuf - 21.2.2010, 17:33


--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
Nab
Дата 25.2.2010, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



if (exists $INC{$module_name}) $packet_name->unimport;

где $module_name = 'CGI/Carp.pm' 
а $packet_name = 'CGI::Carp'

вообщето более правильно сказать:

no CGI::Carp;

Но тут с тонкостями нужно разбираться... я уже подзабыл немного :(


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
arto
Дата 25.2.2010, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: 38
Всего: 40



# perl -MCGI::Carp -le 'no CGI::Carp; croak "hi!"'
[Thu Feb 25 16:09:04 2010] -e: hi! at -e line 1
#
PM MAIL ICQ   Вверх
Nab
Дата 25.2.2010, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



arto, ты как всегда, прийдешь и одной строкой всю малину испортишь smile

IMHO use и no это больше компиляция, а на этапе выполнения import и unimport.

Поправьте меня, потому как я долго был с перлом в разлуке ;)



--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
Logo
Дата 25.2.2010, 18:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Вообще
Код

use Module;
#Тоже что BEGIN {require Module; Module->import}
use Module();
#Тоже что BEGIN {require Module;}

no Module;
#Тоже что BEGIN {require Module; Module->unimport}
no Module();
#Тоже что BEGIN {require Module;}

BEGIN выполняется на стадии компиляции.

Но сабж не о модулях, а о пакетах. sir_nuf_nuf правильно сказал как проверить пакет, а вот как его удалить? Подобные фокусы с пакетами делает модуль Class::Prototyped, правда как он это делает пока не разобрался.

Цитата

А зачем вам понадобилось удалять пакет ?  
Память вам освободить не удастся.
Можно конечо удалить те переменные которые вы импортировали в свой пакет.

Почему не удастся? Надо потому что создается пакет динамически, и убрать его за собой тоже надо бы. См. модуль Class::Prototyped, он удаляет пакеты объектов, которые перестали существовать.

PM MAIL   Вверх
Logo
Дата 25.2.2010, 23:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Разобрался как..
Кстате, Class::Prototyped делает это не полностью, не освобождая переменные и функции(в т.ч. те функции которые сам создал), а только таблицу имен.
upd: Беру свои слова обратно. Походу функции он освобождает функции и переменные, где-то в другом месте кода, причем с учетом счетчика ссылок на них.

Это сообщение отредактировал(а) Logo - 26.2.2010, 11:55
PM MAIL   Вверх
sir_nuf_nuf
Дата 26.2.2010, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 920
Регистрация: 6.1.2008

Репутация: 14
Всего: 31



Итак, поправьте меня если я не прав.

Что такое пакет ? - это набор perl структур (скаляры, массивы, функции и т.п.), сложенные в хеш - таблицу имен.
Они висят в памяти потому что на них есть ссылки из этого самого хеша (точне есть ссылки на globы, а glob ссылаются на все остальное)

Что бы удалить их из памяти - нужно что бы этих ссылок не осталось. 
Для этого нужно:
а) удалить саму таблицу имен.  %Data::Dumper:: = ();
б) удалить все другие ссылки. Таких может быть туева хуча:
Код

package Bu;
use Data::Dumper qw(Dumper);
Bu::Dumper(1); #  Bu::Dumper - тоже нужно удалять
my $x = \&Data::Dumper::Dumper;  # $x - тоже нужно удалять

в) логично было бы еще INC почистить, если пакет загружался из модуль.

Но есть и нюансы:
а) память освободится только для perl
б) XS вы так не выгрузите

Так что в общем случае - это довольно бессмысленная процедура.
Лучше - сформулируйте зачем вам нужно очищать пространства имен ?
Пространстов имен по идее жестко связано с определенным функционалом.
Если вы хотите положить в то же пространство другие функции - это плохо. (В таком случае лучше использовать ООП)


реквестирую XS гуру в тред.  smile 


--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
vadiml
Дата 26.2.2010, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 27.7.2007

Репутация: 5
Всего: 7



> Что такое пакет ? - это набор perl структур (скаляры, массивы, функции и т.п.), сложенные в хеш - таблицу имен.

Боюсь Вы немного путаете пакет и объект.

Модуль -- это фактически файл
Пакет -- это пространство имён, которое при желании можно экспортировать в другое пространство имён
Объект -- это как раз то, что хранится в памяти, хотя и не обязательно что это хеш, если это XS-объект (хотя так и не совсем корректно говорить), то это скаляр, Magic от реального адреса.
Объект удалится из памяти как только на него не останется на него perl-ссылок (если XS -- то и это не факт, там могут быть свои ссылки).

Откомпилировался он сразу, используя use, или не (require, eval) -- тут не имеет значения, подгружается в память всё, предкомпиляция повлияет только на скорость исполнения.
PM MAIL Jabber   Вверх
sir_nuf_nuf
Дата 26.2.2010, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 920
Регистрация: 6.1.2008

Репутация: 14
Всего: 31



Цитата(vadiml @  26.2.2010,  12:38 Найти цитируемый пост)
Пакет -- это пространство имён, которое при желании можно экспортировать в другое пространство имён

да, я в курсе. 
просто в этом треде мы обсуждаем как устроены пространства имен.
устроены они именно в виде хешей содержащих глобы, которые ссылаются на процедуры и переменные данного пакета
экспортирование - по сути копирование одного глобов (или частей) из хеша в хеш

И вопрос был в том как удадить пакет из загруженой программы.

Это сообщение отредактировал(а) sir_nuf_nuf - 26.2.2010, 13:05


--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
Logo
Дата 26.2.2010, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Цитата

Что бы удалить их из памяти - нужно что бы этих ссылок не осталось. 


Можно явно сделать undef всем скалярам, массивам и т.п, и тогда все ссылки идут лесом.
Почему-то недостаточно удалить элемет таблицы имен, надо еще сделать undef typeglob-у.
Таким образом, методом научного тыка подобран такой алгоритм удаления пакета.
- Обходим таблицу имен пакета и делаем:
delete ${"$package\::"}{$key};
undef(*{"$package\::$key"});
- Если надо удалить и то, на что есть ссылки извне, делаем: 
undef(&{"$package\::$key"}); undef(${"$package\::$key"}); и т.д.
Причем до удаления typeglob.

Делаем
Код

# this only works because we're not a multi-level package:
delete($main::{"$package\::"});



Цитата

а) память освободится только для perl


Так все же так. Лишь некоторые системы могут использовать освободившуюся память (Из кемелбука про Perl 5.6).

Цитата

б) XS вы так не выгрузите

Вот этого не знаю...

Еще... написал текст выше и проверил - оказывается если бездумно грохнуть все Perl структуры в пакете, это коснется и того, что в этот пакет экспортировано, чего конечно допустить нельзя. Мне тогда будет достаточно удалить только то, на что нет ссылок извне.
 



Это сообщение отредактировал(а) Logo - 26.2.2010, 14:24
PM MAIL   Вверх
Logo
Дата 26.2.2010, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Цитата

Так что в общем случае - это довольно бессмысленная процедура.
Лучше - сформулируйте зачем вам нужно очищать пространства имен ?
Пространстов имен по идее жестко связано с определенным функционалом.
Если вы хотите положить в то же пространство другие функции - это плохо. (В таком случае лучше использовать ООП)


Class::Prototyped например вынужден такие вещи делать. А у меня модуль для добавления условий в виде Perl кода, для написания разных утилит.
К примеру что бы сделать такую утилиту для поиска картинок.
Код

C:\> myutil.pl --name /^Pict/ --height "$width / 3 * 4" 
#Найти изображения с именем удовлетворяющем /^Pict/ и размерами 3/4 


У условий - свое пространство имен, в которое можно экспортировать функции из других модулей. Создается оно  при создании объекта с набором условий, и удалятся должно при DESTROY этого объекта.

Это сообщение отредактировал(а) Logo - 26.2.2010, 13:58
PM MAIL   Вверх
DurRandir
Дата 26.2.2010, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 14
Всего: 17



Если это утилита для командной строки - я бы не заморачивался и ничего не делал. Всё равно работает недолго. 
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0690 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.