기본 콘텐츠로 건너뛰기

Python

■ 파이썬_01
Nabble.addCssRule(document.styleSheets[0],'.nabble a:link','color:'+document.linkColor); Nabble.addCssRule(document.styleSheets[0],'.nabble a:visited','color:'+document.vlinkColor);
if (!Nabble.isEmbedded) { document.write('Nabble | Old Nabble1'); } else if (false) { document.write('Back to the forum'); } Nabble | Old Nabble1 | Software ≫ SourceForge ≫ SWIG ≫ swig-user Login : Register
Nabble.userHeader(3366);
Swig Python/Autocad binding
View: Threaded Chronologically All Messages Nabble.selectOption(Nabble.get("nabble.viewSelect"),Nabble.tview); New views 9 Messages ? Rating Filter: 0 1 2 3 4 5 Alert me if( Nabble.user == 799921 || Nabble.user == 77858) { document.writeln('Move thread'); }

Swig Python/Autocad binding document.write(Nabble.ratingStars(3));
by document.write(' Mick Duprez document.write(''); document.write(Nabble.formatDateLong(new Date(1219651075018))); Aug 25, 2008; 04:57pm :: Rate this Message: - Use ratings to moderate (?)

document.writeln('Reply | '); Reply | Reply to Author if( Nabble.user == 799921 ) { document.writeln('| Edit'); document.writeln('| Delete'); } else if( Nabble.user == 77858 ) { document.writeln('| Delete'); } document.writeln('| Print'); | Print | View Threaded | Show Only this Message

Hi All,

I've been trying to wrap the AutoCAD ARX api (ARX is the app's C++ SDK) with some success but am stumped at the moment with what may be a simple problem.
The wrapper seems to work with some methods but not others.
For instance, I can call a wrapped global function no problem, this was the first test to see if the wrapper was going to work. Now that I've wrapped some C++ classes I've hit a snag, I seem to be able to call a simple method from a class but when I try to debug other methods the breakpoints are not getting hit and I receive an error and the method in Python fails.

As I have no debugging from Python i can print what the pyobject is to the autocad command line using str(object) and I am indeed getting a pointer to a proxy object, it's functions are just not getting called. The functions are overloaded and swig has produced the code to decide which one to call and I have set bp's at each one and none get hit.
Any help greatly appreciated, if you need the solution or for me to post some code (the .i file is quite large but I can post bit's you might need to look at), just let me know.

Thanks,
Mick.

Some set up details -
winXP SP2
VS2005 std SP1
Python 2.5.2
SWIG 1.3.36
AutoCAD 2008 SDK
google_protectAndRun("render_ads.js::google_render_ad", google_handleError, google_render_ad); if (Nabble.searchterms != null && Nabble.searchterms.length > 0) { Nabble.hilt(Nabble.searchterms, Nabble.get("nabble.msgtxt19139435")); }

Re: Swig Python/Autocad binding document.write(Nabble.ratingStars(3));
by document.write(' Mick Duprez document.write(''); document.write(Nabble.formatDateLong(new Date(1219652839081))); Aug 25, 2008; 05:27pm :: Rate this Message: - Use ratings to moderate (?)

document.writeln('Reply | '); Reply | Reply to Author if( Nabble.user == 799921 ) { document.writeln('| Edit'); document.writeln('| Delete'); } else if( Nabble.user == 77858 ) { document.writeln('| Delete'); } document.writeln('| Print'); | Print | View Threaded | Show Only this Message

Just thought I'd add how the project is set up.

In autocad I've made an arx(dll) plug in that embeds the Python interpreter. From here I have some functions that register python script callbacks in a PyDict which are called from autocad commands.

The callbacks are python methods with no args and they all go through the same C++ static function to call the method. My autocad code catches the command from the user, searches the dict for the command string (key) whose value is the python script callback and it's pushed through the C++ function to execute using the C Python api.

I import my wrapped module/s into the script with the callback and interact with the main app as required then return back to the main app.

hope that gives some further insight,
cheers.
if (Nabble.searchterms != null && Nabble.searchterms.length > 0) { Nabble.hilt(Nabble.searchterms, Nabble.get("nabble.msgtxt19139804")); }

Re: Swig Python/Autocad binding document.write(Nabble.ratingStars(3));
by document.write(' Mick Duprez document.write(''); document.write(Nabble.formatDateLong(new Date(1219922939810))); Aug 28, 2008; 08:28pm :: Rate this Message: - Use ratings to moderate (?)

document.writeln('Reply | '); Reply | Reply to Author if( Nabble.user == 799921 ) { document.writeln('| Edit'); document.writeln('| Delete'); } else if( Nabble.user == 77858 ) { document.writeln('| Delete'); } document.writeln('| Print'); | Print | View Threaded | Show Only this Message

No takers yet :)

Ok, another question that may even solve a big part of the problem.

I've read here and other places that when embedding an interpreter I should also compile the swig interface with it. Is this the correct way?

I've tried both with no real difference, the only thing is I can't call SWIG_init() (which I think is key here) as my wrapper file doesn't have a header file, should I just create one and add it to the interface file so I can 'include' it in my dll entry point file?

I have done extensive searching here and elswhere but a lot of posts glaze over some details that some long time users take for granted (or I still don't understand), so, if someone can give me a basic setup/direction of how I should be doing this that would be greatly appreciated.

My goal is to create a dll that's imported into the main application and embeds a Python interpreter. Using the swig wrapped api I'd like to write scripts callable form the main application through this dll, this part I have worked out fine, it's my interface/glue code with the swig wrapped api that's not working so far.

Thanks,
cheers,
Mick.

if (Nabble.searchterms != null && Nabble.searchterms.length > 0) { Nabble.hilt(Nabble.searchterms, Nabble.get("nabble.msgtxt19198652")); }

Re: Swig Python/Autocad binding document.write(Nabble.ratingStars(3));
by document.write(' mark gossage document.write(''); document.write(Nabble.formatDateLong(new Date(1220237901000))); Sep 01, 2008; 11:58am :: Rate this Message: - Use ratings to moderate (?)

document.writeln('Reply | '); Reply | Reply to Author if( Nabble.user == 220699 ) { document.writeln('| Delete'); } else if( Nabble.user == 77858 ) { document.writeln('| Delete'); } document.writeln('| Print'); | Print | View Threaded | Show Only this Message

>
> No takers yet :)
>
> Ok, another question that may even solve a big part of the
> problem.
>
> I've read here and other places that when embedding an
> interpreter I should
> also compile the swig interface with it. Is this the
> correct way?
>
> I've tried both with no real difference, the only thing
> is I can't call
> SWIG_init() (which I think is key here) as my wrapper file
> doesn't have a
> header file, should I just create one and add it to the
> interface file so I
> can 'include' it in my dll entry point file?
>
> I have done extensive searching here and elswhere but a lot
> of posts glaze
> over some details that some long time users take for
> granted (or I still
> don't understand), so, if someone can give me a basic
> setup/direction of how
> I should be doing this that would be greatly appreciated.
>
> My goal is to create a dll that's imported into the
> main application and
> embeds a Python interpreter. Using the swig wrapped api
> I'd like to write
> scripts callable form the main application through this
> dll, this part I
> have worked out fine, it's my interface/glue code with
> the swig wrapped api
> that's not working so far.
>
> Thanks,
> cheers,
> Mick.
>
...[show rest of quote]
Hello Mick,

Where to start....
As far as I read from you post, what you a looking to do is to embed a python interpreter into your C/C++ Autocad application, and then have it call a bunch of the Autocad functions.
This is two seperate matters: 1. embedding the python interpreter, 2. calling Autocad functions.
SWIG will easily perform 2 for you, but on part 1, you have to DIY.
Dealing with part 2 first: what you do is create a .i file with all your functions to wrapper in that, and feed to SWIG. It will then create the bindings for you. Job done.

For part 1, this is harder. The python documentation on embedding is not very good. I you believe: http://davidf.sjsoft.com/mirrors/mcmillan-inc/embed.html I guess python is not meant for this task.
However http://www.linuxjournal.com/article/8497 does give a very simple example of embedding which you could work with.
To add the SWIG bindings to this is just one more line of code.
Expanding one of the examples from the previous article:

void exec_pycode(const char* code)
{
Py_Initialize();
Example_init(); // call SWIG module
PyRun_SimpleString(code);
Py_Finalize();
}

But the whole business of embedding Python is not so easy to do. I would start by just adding a simple embed (as this) and try to call some python from Autocad, then try adding one autocad function to see if you can do it.

Hope this helps,
Mark




-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Swig-user mailing list
Swig-user@...
https://lists.sourceforge.net/lists/listinfo/swig-user

if (Nabble.searchterms != null && Nabble.searchterms.length > 0) { Nabble.hilt(Nabble.searchterms, Nabble.get("nabble.msgtxt19248314")); }

Re: Swig Python/Autocad binding document.write(Nabble.ratingStars(3));
by document.write(' Mick Duprez document.write(''); document.write(Nabble.formatDateLong(new Date(1220243199877))); Sep 01, 2008; 01:26pm :: Rate this Message: - Use ratings to moderate (?)

document.writeln('Reply | '); Reply | Reply to Author if( Nabble.user == 799921 ) { document.writeln('| Edit'); document.writeln('| Delete'); } else if( Nabble.user == 77858 ) { document.writeln('| Delete'); } document.writeln('| Print'); | Print | View Threaded | Show Only this Message

Thanks Mark,
I have the Python interpreter embeded ok and I have manually wrapped some code with little problem, I can use the COM api from Python scripts at the moment and I have the callbacks all organised.
I have successfully compiled a SWIG module and I can get a global method to work, but if I try to call a class method I get an error and my callback fails to finish the task.
I have set break points in the SWIG code for debugging but they are not being hit, the global method gets hit ok, just not the class methods.

There is nothing real special about the C++ classes I'm wrapping and SWIG is generating what looks like the class interface code ok, maybe I need an extra swig preprocessing helper or something(?).
I'll do some more study tonight and see if I can spot anything else I'm missing.
Cheers,
Mick.

PS. As I only have limited debugging on the python side, I am using a print statement to see if I have created an object in Python, it's seems as though I am but I don't think I'm getting one on the C++ side, and that's where the problem lies I think.
if (Nabble.searchterms != null && Nabble.searchterms.length > 0) { Nabble.hilt(Nabble.searchterms, Nabble.get("nabble.msgtxt19248754")); }

Re: Swig Python/Autocad binding document.write(Nabble.ratingStars(3));
by document.write(' Mick Duprez document.write(''); document.write(Nabble.formatDateLong(new Date(1220869144162))); Sep 08, 2008; 07:19pm :: Rate this Message: - Use ratings to moderate (?)

document.writeln('Reply | '); Reply | Reply to Author if( Nabble.user == 799921 ) { document.writeln('| Edit'); document.writeln('| Delete'); } else if( Nabble.user == 77858 ) { document.writeln('| Delete'); } document.writeln('| Print'); | Print | View Threaded | Show Only this Message

So far I've tried just about everything, features, inline helpers and read the doc's more than a few times, I just can't get something that seems/claims to be so simple to do anything useful. The only thing that seems to work is if I wrap what I need into %inline helper functions.

Here is part of one of the more complicated classes, is there something obvious I'm missing here?
The only time you create a new object is if you're creating a new file, hence the only ctor.
Normally you wold use a global function to get the 'active' db object then use its methods add/remove/modify obects, when I call getBlockTable below it fails, if I try to unload the dll hosting the interpreter it crashes the main app.

class AcDbDatabase: public AcRxObject, public AcHeapOperators
//
// A class whose instances represent an entire DWG file,
// aka database itself.
//
{
public:
virtual AcRxClass* isA() const;
static AcRxClass* desc();
static AcDbDatabase* cast(const AcRxObject* inPtr)
{ return ((inPtr == NULL) || !inPtr->isKindOf(AcDbDatabase::desc()))
? NULL : (AcDbDatabase*)inPtr; };

// constructor & destructor
AcDbDatabase(bool buildDefaultDrawing = true,
bool noDocument = false);
virtual ~AcDbDatabase();

// a typical call to get another object I've wrapped also:
Acad::ErrorStatus getBlockTable (AcDbSymbolTable*& pTable,
AcDb::OpenMode mode);

.... and so on.


Here's some python code, please excuse it :) -

def addline():
try:
sp = pyacdb.AcGePoint3d(30.0,45.0,0.0)
ep = pyacdb.AcGePoint3d(120.0,120.0,0.0)
line = pyacdb.AcDbLine(sp,ep)
pyacdb.acutPrintf ('\nIn addline6.1 ...\n') #this works fine, global function
pDb = pyacdb.acdbWorkingDatabase()
pyacdb.acutPrintf ('\nIn addline7...\n') #I'm getting to here....
pDb.getBlockTable(pBt, AcDb.kForRead)
pyacdb.acutPrintf ('\nIn addline7.1..\n') #not making it here though!!!
pBt.getAt('*Model_Space',pBtr,AcDb.kForWrite)
pyacdb.acutPrintf ('\nIn addline7.2..\n')
pBt.close
pyacdb.acutPrintf ('\nIn addline8...\n')
id = pyacdb.AcDbObjectId()
pyacdb.acutPrintf ('\nIn addline9...\n')
pBtr.appendAcDbEntity(id,line)
pyacdb.acutPrintf ('\nIn addline10...\n')
pBtr.close
pyacdb.acutPrintf ('\nwOOOOt!!...\n')

except:
msg = "Unexpected error:" + sys.exc_info()[0]
pyacdb.acutPrintf (msg)
raise

and here's the main part of the calling method in the interpreter hosting dll -

// grab the callback from the PyDict and call it:
PyObject *arglist;
PyObject *result, *func;
arglist = Py_BuildValue("()");
func = PyDict_GetItemString(pCmdDict,pyStr);
if (PyCallable_Check(func))
{
result = PyEval_CallObject(func, arglist);
}
Py_DECREF(arglist);
if (result == NULL)
{
acutPrintf(_T("PyArxError: Failed to call Python callback.\n"));
return;
}
Py_DECREF(result);
if(pyStr)
{
free(pyStr);
}

What I do here is, when I load the interpreter I call into an 'initialiser' .py file which calls an embedded method using straight python extension code to load method callbacks into a dict object, the application calls a method callback in the dict by it's string key as a command using the code above.

This works pretty well so far (all though it needs more error handling to stop trashing the host's memory), it seems as if I'm either loosing my pointer to the database object or it's not 'really' creating one??

I feel I'm just one step away but my eyes have all but glazed over from all this study and testing to no avail. Swig is wrapping as much or as little as I need with little trouble, it's just not working as I would have hoped.

Thank you,
Mick.



if (Nabble.searchterms != null && Nabble.searchterms.length > 0) { Nabble.hilt(Nabble.searchterms, Nabble.get("nabble.msgtxt19369352")); }

Re: Swig Python/Autocad binding document.write(Nabble.ratingStars(3));
by document.write(' Steven Hirsch document.write(''); document.write(Nabble.formatDateLong(new Date(1220874578000))); Sep 08, 2008; 08:49pm :: Rate this Message: - Use ratings to moderate (?)

document.writeln('Reply | '); Reply | Reply to Author if( Nabble.user == 804348 ) { document.writeln('| Delete'); } else if( Nabble.user == 77858 ) { document.writeln('| Delete'); } document.writeln('| Print'); | Print | View Threaded | Show Only this Message

On Mon, 8 Sep 2008, Mick Duprez wrote:

> So far I've tried just about everything, features, inline helpers and read
> the doc's more than a few times, I just can't get something that
> seems/claims to be so simple to do anything useful. The only thing that
> seems to work is if I wrap what I need into %inline helper functions.
>
> Here is part of one of the more complicated classes, is there something
> obvious I'm missing here?
> The only time you create a new object is if you're creating a new file,
> hence the only ctor.
> Normally you wold use a global function to get the 'active' db object then
> use its methods add/remove/modify obects, when I call getBlockTable below it
> fails, if I try to unload the dll hosting the interpreter it crashes the
> main app.
...[show rest of quote]

I must be missing something in your sample code. Where's the constructor
for the database object? You are showing code that tries to use the
object, but are not detailing where it comes from and how?

Steve

-


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Swig-user mailing list
Swig-user@...
https://lists.sourceforge.net/lists/listinfo/swig-user

if (Nabble.searchterms != null && Nabble.searchterms.length > 0) { Nabble.hilt(Nabble.searchterms, Nabble.get("nabble.msgtxt19370442")); }

Re: Swig Python/Autocad binding document.write(Nabble.ratingStars(3));
by document.write(' Mick Duprez document.write(''); document.write(Nabble.formatDateLong(new Date(1220905863001))); Sep 09, 2008; 05:31am :: Rate this Message: - Use ratings to moderate (?)

document.writeln('Reply | '); Reply | Reply to Author if( Nabble.user == 799921 ) { document.writeln('| Edit'); document.writeln('| Delete'); } else if( Nabble.user == 77858 ) { document.writeln('| Delete'); } document.writeln('| Print'); | Print | View Threaded | Show Only this Message

Steven Hirsch wrote:
On Mon, 8 Sep 2008, Mick Duprez wrote:

> So far I've tried just about everything, features, inline helpers and read
> the doc's more than a few times, I just can't get something that
> seems/claims to be so simple to do anything useful. The only thing that
> seems to work is if I wrap what I need into %inline helper functions.
>
> Here is part of one of the more complicated classes, is there something
> obvious I'm missing here?
> The only time you create a new object is if you're creating a new file,
> hence the only ctor.
> Normally you wold use a global function to get the 'active' db object then
> use its methods add/remove/modify obects, when I call getBlockTable below it
> fails, if I try to unload the dll hosting the interpreter it crashes the
> main app.

I must be missing something in your sample code. Where's the constructor
for the database object? You are showing code that tries to use the
object, but are not detailing where it comes from and how?

Steve
...[show rest of quote]
Hi Steve,
here's the constructor/destructor -

// constructor & destructor
AcDbDatabase(bool buildDefaultDrawing = true,
bool noDocument = false);
virtual ~AcDbDatabase();

At most times you wouldn't need to create a db object as it already exists but you can get a pointer to it using some global functions, the acdbWorkingDatabase() method in the python script is a wrapped helper that 'is' getting called. the eg.
pDb = pyacdb.acdbWorkingDatabase() # get a pointer to a pDb (AcDbDatabase) object

These appear to be working when stepping through code in the debugger but when I call a method on the db object it isn't entering the swig wrapper code and my break points are not being hit.

I wouldn't think you would need an empty/default ctor if the db already existed and I'm not sure how the hosting app would respond creating an object without the default param's?
I did read somewhere though about swig making a new object that then uses a copyctor to put the pointer in but I don't think the host app would like that, does swig do this for 'every' class object being wrapped?

thanks.
Mick.
if (Nabble.searchterms != null && Nabble.searchterms.length > 0) { Nabble.hilt(Nabble.searchterms, Nabble.get("nabble.msgtxt19380559")); }

Re: Swig Python/Autocad binding document.write(Nabble.ratingStars(3));
by document.write(' Mick Duprez document.write(''); document.write(Nabble.formatDateLong(new Date(1221045819290))); Sep 10, 2008; 08:23pm :: Rate this Message: - Use ratings to moderate (?)

document.writeln('Reply | '); Reply | Reply to Author if( Nabble.user == 799921 ) { document.writeln('| Edit'); document.writeln('| Delete'); } else if( Nabble.user == 77858 ) { document.writeln('| Delete'); } document.writeln('| Print'); | Print | View Threaded | Show Only this Message

Ok, a bit more testing revealed I can call a method if I wrap the c++ code into C helper functions, the C++ class functions are still not working.

Here's my code in the interface file for the helper functions, these work fine, the C++ code is as per the earlier post (or a typical class).
.....................
%inline {
AcDbDatabase* acdb_getCurrentDb()
{
AcDbDatabase* pDb;
pDb = acdbHostApplicationServices()->workingDatabase();// api func that returns active db*
return pDb;
}
}

%inline {
const ACHAR* acdb_getFileName(AcDbDatabase* pDb)
{
const ACHAR* filename;
pDb->getFilename(filename);// get the db*'s filename
return filename;
}
}

int acutPrintf(const ACHAR* format, ...); // function to print string output to autocad command line/prompt

......................

these are the 2 python script functions I call that grab the current database object pointer and then get it's filename member variable.

.........................

def print_msg1(): #called with 'PY1' command
#using swig wrapper, no helper:
pDb1 = pyacdb.acdbWorkingDatabase()
dbstring = str(pDb1) + '\n'
pyacdb.acutPrintf(dbstring)
filename = ' '
pDb1.getFilename(filename) #call a C++ member function, fails here!!!!
filename = '\n' + filename + '\n'
pyacdb.acutPrintf(filename)

def print_msg2():#called with 'PY2' command
#using swig wrapper using helper:
pDb2 = pyacdb.acdb_getCurrentDb()
dbstring = str(pDb2) + '\n'
pyacdb.acutPrintf(dbstring)
filename = pyacdb.acdb_getFileName(pDb2) #a C global function
filename = '\n' + filename + '\n'
pyacdb.acutPrintf(filename)

..............................

It seems that I'm getting the same pointer for both methods, I just can't use it to call class methods of the C++ class wrapper??

Here's the output -

Command: PY1 <----- class wrapper output >
PyArxError: Failed to call Python callback. <---- this is from the interpreter dll Command: PY2 <------ using helper/s output >
C:\Documents and Settings\Mick\My Documents\Drawing1.dwg

Hoping this may shed some light on the problem, thanks.
Mick.
if (Nabble.searchterms != null && Nabble.searchterms.length > 0) { Nabble.hilt(Nabble.searchterms, Nabble.get("nabble.msgtxt19411391")); }


//Nabble.gquery = 'test'; //Nabble.topicDumpSearch = true; if (Nabble.gquery!=null) { if (Nabble.topicDumpSearch) { Nabble.get('nabble.searchResults').innerHTML = '
Other threads matching \"'+Nabble.gquery+'\":
'+ '
Search Nabble for "'+Nabble.gquery+'"' ); } } if( Nabble.prev ) Nabble.writeReturnToLink(Nabble.prev);


≪ Search Nabble for "python autocad"

Free embeddable forum powered by Nabble Forum Help

(function(){ if( Nabble.cur ) { var t = Nabble.get( "nabble.i" + Nabble.cur ); if( t ) { t.style.visibility = "visible"; } } if( Nabble.gquery!=null ) { var t = Nabble.get("nabble.searchQuery"); t.value = Nabble.gquery; Nabble.selectOption(Nabble.get("nabble.searchSelect"),"n"); if( !Nabble.notRed ) { t.className += "error-message"; t.style.borderStyle = "solid"; t.style.borderWidth = "3px"; t.style.backgroundColor = Nabble.currentStyle(Nabble.get('nabble')).backgroundColor; } } })(); Nabble.analytics(); _qoptions={ qacct:"p-34EL1DZyJypTI" };








댓글

이 블로그의 인기 게시물

80040154 오류로 인해 CLSID가 {xxxx-...}인 구성 요소의 COM 클래스 팩터리를 검색하지 못했습니다.

원문보기 .NET 으로 만든 응용프로그램에서 com 객체를 호출한 경우 Windows7 64bit 에서 제목과 같은 에러가 발생했다. Win32 COM 과 .NET 프로그램간의 호환성 때문에 생긴 문제였다. 원인은 .NET 실행시 JIT 컴파일러에 의해 최적화된 기계어로 변환되기 때문.. Win32 COM은 컴파일시.. Win32 COM에 맞춰 빌드 속성에서 하위버전으로 맞춰 컴파일을 다시하는 방법도 있지만 메인 프로젝트가 .NET이라면 참조되는 모든 프로젝트를 다 바꿔야할 노릇.. 또 다른 방법은 COM+를 이용하여 독립적으로 만드는 것이다. 분리시키는 방법은 아래 주소해서 확인할 수 있다. http://support.microsoft.com/kb/281335 나의 경우는 Win32 COM DLL을 64비트 .NET 프로그램에서 참조하니 COM 객체를 제대로 호출하지 못하였습니다. 그래서 .NET 프로그램의 Target Machine을 x86으로 설정하니 제대로 COM 객체를 호출하였습니다.

[Pyinstaller] 실행 파일 관리자 권한 획득하기

고객사에서 일부 사용자에게서 프로그램 오류가 발생한다며 아래와 같이 에러 캡처를 보내왔습니다. 프로그램에서 로그를 남기기 위해 로그 파일을 생성하는데 권한의 문제로 로그 파일을 생성하지 못해 프로그램 오류가 발생한 것 같습니다. 처음에는 Python 코드에서 관리자 권한을 요청하는 코드를 넣으려고 했는데, 실제로 Stackoverflow를 찾아보면 이런 내용이 나옵니다. 프로그램이 관리자 권한으로 실행되지 않았다면 관리자 권한으로 다시 프로그램을 실행시키는 코드입니다. import os import sys import win32com.shell.shell as shell ASADMIN = 'asadmin' if sys.argv[-1] != ASADMIN: script = os.path.abspath(sys.argv[0]) params = ' '.join([script] + sys.argv[1:] + [ASADMIN]) shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params) sys.exit(0) 하지만 개인적으로 이런 방식은 마음에 들지 않았고 조금 더 찾아보니 Pyinstaller로 exe 파일을 만들 때 옵션을 설정하여 관리자 권한을 요청하도록 할 수 있다고 합니다. --uac-admin을 옵션에 추가하면 프로그램 실행 시 관리자 권한을 요청할 수 있습니다. pyinstaller.exe --uac-admin sample.py 하지만 안타깝게도 이 방식은 원하는 대로 동작하지 않았습니다. 마지막으로 manifest 파일을 이용하여 시도해보았습니다. spec 파일을 이용하여 pyinstaller로 빌드하면 <실행 파일 이름>.manifest 라는 파일이 생성됩니다. 파일에서 아랫부분을 찾아볼 수 있습니다. <security> <re

초간단 프로그램 락 걸기

프로그램에 락을 걸 일이 생겨났다. 하드웨어 락을 걸면 쉬울텐데 그 정도는 아니고 프로그램의 실행 날짜를 제한 해 달라고 한다. 그래서 파일(license.lic)을 가지고 락을 걸리고 결정을 했다. 요구 사항은 아래와 같다. 1. license.lic 파일이 없으면 프로그램을 실행 할수 없게 한다. 2. 지정한 날짜를 넘어서는 프로그램을 실행 할수 없게 한다. 3. 사용자가 시스템 날짜를 되돌렸을때 인식하여 프로그램을 실행 할수 없게 한다. 음.... 1.번 문제는 사용자가 프로그램을 실행하기 위해서 license.lic 파일을 받아야만 한다. license.lic 파일에는 최근 실행 날짜/종료날짜 이런식으로 적도록 한다.(물론 내용은 암호화 한다.) 최근 실행날짜는 프로그램이 실행때마다 업데이트 하도록 하고 시스템 날짜와 비교하여 시스템 날짜가 최근 실행 날짜보다 이전의 날짜면 시스템 날짜를 되돌렸다고 인식하도록 한다.(3.번 문제 해결) 시스템 날짜와 종료 날짜를 비교하여 시스템 날짜가 종료 날짜를 넘으면 프로그램을 실행 할수 없도록 한다.(2.번 문제 해결)