<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Maysam senaps</title>
        <link>https://virgool.io/feed/@senaps</link>
        <description>دولوپر تازه کار پایتون، عاشق گنو/لینوکس، علاقمند به امنیت :)</description>
        <language>fa</language>
        <pubDate>2026-06-16 18:13:17</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/16698/avatar/avatar.png?height=120&amp;width=120</url>
            <title>Maysam senaps</title>
            <link>https://virgool.io/@senaps</link>
        </image>

                    <item>
                <title>چطوری از ایران، شغل دولوپری در بیرون ایران پیدا کنیم</title>
                <link>https://virgool.io/@senaps/%DA%86%D8%B7%D9%88%D8%B1%DB%8C-%D8%A7%D8%B2-%D8%A7%DB%8C%D8%B1%D8%A7%D9%86-%D8%B4%D8%BA%D9%84-%D8%AF%D9%88%D9%84%D9%88%D9%BE%D8%B1%DB%8C-%D8%AF%D8%B1-%D8%A8%DB%8C%D8%B1%D9%88%D9%86-%D8%A7%DB%8C%D8%B1%D8%A7%D9%86-%D9%BE%DB%8C%D8%AF%D8%A7-%DA%A9%D9%86%DB%8C%D9%85-i5jww2sdgrxh</link>
                <description>سلاممن میثم هستم و پدر فِیلد‌ مصاحبه‌های ایرانی و خارجی. با این حال این قابلیت رو داشتم که لاقل مصاحبه‌ها رو بگیرم و بعد فیل بشم. برای خیلی‌ها که خیلی از من کار‌بلد تر وحرفه‌ای تر هستن گاها این سوال پیش میاد که بهترین روش برای پیدا کردن کار چیه و من به شخصه چطوری کارها رو گیر میارم. توی این پست میخوام تجربه شخصیم رو از پیدا کردن کار‌ها، فرستادن رزومه، مصاحبه‌های مختلف و... براتون به اشتراک بگذارم.ولی همون اول کار براتون گفتم که من تا حالا توی عمرم فقط توی یک مصاحبه پذیرفته شدم که الان هم توی اون شرکت دارم کار می‌کنم هنوز. پس اگر بعد از مصاحبه هم براتون مهمه، احتمالا اینجا جای درستی براتون نیست :)کارها رو از کجا پیدا می‌کنم؟مهم‌ترین مسئله پیدا کردن شرکت‌هاست. مسئله اینه که امازون و گوگل و اسپاتیفای و فیس‌بوک رو همه می‌شناسیم، ولی مارکت بیرون ایران مشخصا توی اروپا کلی شرکت‌های ریز و درشت ۴۰-۵۰ نفره مثل داخل ایران داره که میشه روشون حساب باز کرد. قضیه برای اون شرکت های معروف کاملا متفاوته، پس من ۲ تا تیکه می‌کنم قضیه رو... شرکت‌های کاملا شناخته شدهشرکت‌های خیلی بزرگ یا شناخته شده رو من معمولا حتی مصاحبه اولیه رو هم نتونستم بگیرم و فقط اچ‌ار رفتم و یا حداکثر تکنیکال اینترویو اول. ردهت، امازون، موزیلا و کنونیکال و ویکی‌پدیا شرکت‌هایی هستن که وقتی کله‌ام بو قرمه سبزی می‌داد براشون رزومه میدادم. این شرکتا توی سایت خودشون یه بخش careers و یا jobs دارن که می‌تونید در اونجا ثبت نام بکنید، بر اساس کشور/شهر/شغل مورد نظر سرچ بزنین و درخواست کار بزنین. روال کار به این صورته که بعد از یکی دو هفته یه ایمیل میگیرید از HR که بهتون میگه از ایران دولوپر نمی‌گیریم و قضیه کاملا کنسل می‌شه.یا اینکه شما رو وارد پروسه مصاحبه‌اشون می‌کنن. در مورد پروسه در ادامه می‌گم.شرکت‌های کوچیک‌تراولین منبع من، استک اورفلو هستش. بخش مشاغل این ساعت فوق‌العاده عالی هست. شما میتونید بر اساس استکتون،  کشور مقصد، سطح تخصصی که میخواد و همچنین اپشن‌هاش(ویزا ساپورت - ریلوکیشن ساپورت) سرچ کنین.اگهی‌ها شما رو یا به سایت دیگه می‌برن یا در محل ایزی اپلای می‌کنین و همونجا رزومتون فرستاده میشه.دومین منبع من، لینکد‌این هستش. بخش مشاغل این سایت رسما بازار شام هستش. کشور و استک مد نظر رو میزنین، اگهی‌های یک هفته اخیر رو سورت می‌کنین و بعد شروع می‌کنین به نگاه کردن.اگهی‌هایی که به یه زبون دیگه غیر از انگلیسی هستن کلا دراپ می‌شن!( من کمی المانی بلدم و می‌تونم تک‌تاک رو توی متن تشخیص بدم، ولی این تیپ آگهی‌ها بازارشون مشخصا گاهی حتی فقط شهر هدف هستش و شما از مثلا مونیخ به برلینشون اگهی بزنی باز رد میشی :)) پس خودتون رو اذیت نکنین و سریع رد بشین.گروه بعدی اگهی‌ها، اگهی‌های easy apply هستن. این اگهی‌ها گول‌زننده ترین هستن. شما با کلیک سوم برای این شغل &quot;فکر می‌کنین&quot; که اپلای کردین. در صورتی که اگر متن رو به دقت خونده باشید، می‌بینید که اون نوشته به johndoe@gmail.com رزومتون رو بفرستید :))استراتژی من برای اگهی‌های انگلیسی زبان به این صورت هستش که ریکوایرمنت‌هاشون رو نگاه می‌کنم، اگر استکشون چیزی بود که من داشتمش، سریعا ایمیل رو پیدا می‌کنم و براشون یه متن (این متن خیلی خیلی مهمه و میگم‌ در موردش) می‌نویسم و رزومه رو ایمیل می‌کنم.دسته بعدی اگهی‌ها، اگهی‌هایی هستن که کلیک کردن روش شما رو به یه سایت دیگه می‌بره، مثل استک بعدا براتون توضیح می‌دم این‌ها رو که چطوری هستن. فعلا داریم شرکت‌ها رو پیدا می‌کنیم...بازم به لینکداین بر می‌گردم و یه سری کاربرد دیگه‌اش رو می‌گم.منبع سوم من، گلس‌دور یا glassdor هستش. این سایت عالیه. بعدا بهش می‌پردازم که چه کاربردهایی داره!توی گلس‌دور هم مثل لینکداین سرچ می‌زنین، اگهی‌های به زبون غیر از انگلیسی رو دراپ می‌کنین، و ایمیلی‌ها رو با یه متنی ایمیل می‌زنین و بقیه رو می‌رین به یه سایت دیگه...سایت‌های اپلایخوب، از هر طریقی که اگهی رو پیدا کرده باشید، با کلیک روی لینک اپلای دو حالت پیش میاد. یا میرید به سایت خود شرکت که کمتر پیش میاد و اونجا نیازمندی هاش رو پر می‌کنین. معمولا ازتون اسم و کشور و ایمیل و تحصیلات و رزومه و یه متن! می‌خوان. بعد از تکمیل قضیه بهتون ایمیل میزنن که همه‌چیز اوکیه. شرکت‌های شناخته شده بهتون پراگرس وضعیت اپلیکیشن رو هم از سایتشون می‌دن و شما باید دستی برگردید و چک کنین که اپلیکیشنتون در چه وضعیتیه و چه تصمیمی براش گرفته شده.بقیه شما رو به یه سایت لوکال کاریابی می‌برن. این سایت‌ها ریز هستن، از شما یه سری دیتای خیلی کلی شامل اسم و فامیل و ایمیل و رزومه و یه متن می‌خوان و بعد رزومتون رو می‌فرستن. به این سایت‌ها به چشم جابینجای اون کشور نگاه کنین!! اکثریت مطلق اگهی‌ها به این مدل اگهی‌ها لینک شدن و در حقیقت یه نفر خودش دستی و الکی لینک اگهی رو به لینکداین یا گلسدور فرستاده.اگر مقصد بخصوصی دارید، بعد از مدتی دستتون میاد که اکثر اگهی‌های اون کشور یا حتی شهر بخصوص شما رو به سایت خاصی میبرن و خوب، می‌تونید از اون سایت استفاده کنین برای گشتن دنبال کار و گزینهٔ بهتری هم هستن چون خود شرکت‌های ریز محلی رو اینجا می‌تونین پیدا کنین.داستان این متنه چیه؟خوب!! مهم‌ترین چیز. ببینید رزومه رو بر اساس هر شغل میشه نوشت، میشه مثل من یه رزومه داشت که ۲ ساله بهش دست نزدید و کل رفقاتون فحشون می‌دن که این چیه نوشتی درستش کن! رزومه چند ثانیه به شما فرصت می‌ده برای نگاه کردن، ولی اون متنی که همراهش می‌فرستید برای شرکت مربوطه اصطلاحا cover letter  اسمش هست و من تجربتا فهمیدم که این از خود رزومه هم مهم‌تره!در مورد رزومه اگر میخواید تخصصی وارد بشید، باید ببینید کشور مقصدتون چه مدل رزومه‌ای داره و نرمال رزومه‌هاش چطوریه. شخصا گاهی رزومه خوندم و صفحه اول که تموم شد تصمیمم رو گرفتم که طرف رد بشه یا نه!:) بقیه‌اش رو همینجوری اسکرول می‌کنم ببینم چی نوشته شاید چشمم چیزی رو گرفت.گاها رزومه شما رو یه نرم‌افزار بررسی می‌کنه و دنبال یه سری کلید واژه توش می‌گرده ببینه دارید یا نه و اگر پیداشون نکنه، رزومه شما به دست یه ادم نمی‌رسه. خودتون می‌دونید ولی من جلوی اسم پایتون ۵ تا ستاره نمی‌ذارم  که دوتاش رنگیه و سه تاش خاموش! یا بدتر از اون یه پراگرس بار.کاور لترخیلی خلاصه و کوتاه و دقیق توضیح بدین توی چند خط که چرا باید شما رو استخدام کنه شرکت؟ مثلا من یه همچین متنی رو به عنوان کاور لتر فرستادم برای اخرین شرکتی که الان سومین مصاحبه رو هم باهاش داشتم! طبق معمول کاملا غیر استاندارده متن من و تمام چک‌باکس‌های چطوری کاورلتر ننویسیم رو مارک می‌کنه. ولی من اینجوری می‌زنم شما کاور لتر خودتون رو بنویسید(سرچ کنین ببینید چی مرسومه برای کاور لتر و یه دونه درستش رو بنویسید)Hi there, I&#x27;ve been working with your stack of technologies for about 3 years. I have used flask, mariadb, rabbitmq, celery and redis on a centos machine all day everyday for the past 2-3 years. I have experience with frontend technologies such as reactjs and vuejs though Im not a very sophisticated frontend developer. we use pytest, docker and docker-compose on a drone-ci machine and gogs/git-server for testing and version control. I have experience configuring nginx and application deployemnet.این متن البته به شیوه استاندارد نوشته شدن حتما باید نوشته بشه چرا؟ چون کسی که داره رزومه شما رو بررسی می‌کنه برای پیدا کردن دکمه اینتر که اپلیکیشن شما رو رد بکنه سرش رو میگیره پایین چند ثانیه دنبالش می‌گرده و بعد می‌زنتش! یعنی اساسا نمی‌دونه برنامه نویسی و اینا چیه! خفن‌ترین کاری که با کامپیوترش کرده هم ریستارت کردن کامپیوترش وقتی هنگ کرده بوده. یا ممکنه یه بابایی باشه که ۱۵ سال پیش با سی داشته دیتابیس می‌نوشته و اصلا دید نداره به تکنولوژی روز. پس لازمه که خیلی خلاصه و سریع براش بگید که شما دقیقا با استک و روال کاری اونها اشنایی دارید و شانس بیشتری برای خودتون و رزومتون بخرید.من هر کاری که وقت گذاشتم و تخصصا برای اونها کاور لتر نوشتم رو به مصاحبه رسیدم بنابراین اهمیت خیلی خوبی داره.اوکی، حالا چی؟خوب، حالا که روزمه ها رو فرستادین، فرداش بیاید و ایمیلتون رو چک کنین. بعضی از این شرکتا ممکنه بهتون ایمیل زده باشن و خواسته باشن که یه تایم بذارید برای مصاحبه تلفنی. بهشون بگید که به &quot;وقت اونها&quot; چه روزهایی و چه ساعت‌هایی وقت دارید و راه‌های تماس باهاتون رو هم بهشون بدید. مثلا ۳ شنبه به وقت سوئد ساعت ۲ تا ۵ اوکی هستم. بعد که قرار مصاحبه اولیه ست شد، سریعا برید به لینکداین و گلس‌دور رو توی دوتا تب باز کنین. اسم شرکت مربوطه رو توشون بزنین، اگهی شغلی رو پیدا کنین که چی خواستن و دقیقا کارشون چیه و چیکار می‌کنن. چند نفر کارمند دارن، کجان و چه مدل ادمایی باهاشون کار میکنن. مصاحبه‌کننده رو(معمولا اچ‌ار) پیدا کنین و ببینید کیه و چیه و بک‌گراندش چیه. ادمایی که توی شرکت کار میکنن و بک‌گراندشون رو ببینید(دولوپر‌های تیمی که براش زدین) مثلا اگر بکند دولوپر رو اپلای کردین، ببنیید بقیه انجینیر‌ها و یا بکند دولوپر‌هاشون کین، کجایین، چقدر قبل از شرکت فعلی کار کردن و چه سمتی داشتن و کلا چیکاره بودن. اینجوری دستتون میاد که شرکت مربوطه چه مدل ادمایی می‌گیره.مثلا اگر ۵ تا دولوپر داره که ۳ تاشون قبلا امازون بودن و ۱یشون فیس‌بوک، احتمالا همچین شرکتی شرکت مقصد بسیار کله گنده هستش و سطح بالا باید بگیرید برای مصاحبه‌هاش و حرفه‌ای تر باشید...توی گلسدور میتونید یه شرکت رو سرچ کنین و یه سری رویو عمومی که کارمنداش نوشتن رو ببینید و یا میانگین حقوق و این صحبتا رو ببینید. گاهی ممکنه کسی روند مصاحبه رو هم نوشته باشه.برای مصاحبه‌ها یه جایی از خونه رو انتخاب کنین که اینترنت داشته باشید، لپ‌تاپ و گوشی رو شارژ کنید و از قبل هماهنگ باشدی با خونواده یه دفعه مامانتون به سبک SWAT با لگد نزنه به در و بیاد تو داد و بیداد کنه :)مصاحبه اچ‌ارمصاحبه اول، معمولا اشناییه. معمولا اینجوری شروع میشه که شرکتشون چیه، چیکار می‌کنه و دنبال چه کسی میگردن برای پوزیشن و اولین سوال به طور مطلق برای من این بوده که از خودت برام بگو.این مصاحبه اچ‌ار هستش بنابراین با شخص شما کار دارن. اسمتون رو تکرار کنین، سنتون رو بگین و بعد سریع برید سراغ اصل مطلب. توی شرکت فعلی‌ای که دارید کار می‌کنین چیکاره‌اید. من توضیح میدم مثلا که بکند دولوپر توی یه تیم ۴-۵ نفره هستم که اپلیکیشنمون فلان کاربرد رو داره و شرکتمون فلان مارکت رو فعاله و چقدر درگیر بازاره. بعد توضیح میدم که با چه استک و تکنولوژی‌هایی کار می‌کنم و اینجا شما باید عینا اون متن کاور لتر رو تکرار کنین!! یعنی کل استکشون که باهاش درگیر بودین رو به گوش طرف برسونین که باهاش درگیر بودین. به نظرم رسیده که درست بتونید حرف بزنید و توضیح بدید به سادگی که توی شرکت چیکار کردید، در حقیقت دارید سطح زبانتون رو هم نشون میدین. بنابراین این سوال که معمولا ثابته و گاها ممکنه تریکی بشه رو از قبل اماده کنین و بدون تپق زدن بگیدش. سوالات بعدی ممکنه شامل چرا میخوای بیای اینجا و راجع‌به شرکت ما چی میدونی میشه.پر واضحه که شما عاشق کشورشون هستید، شرکتشون رو شناختید و استکشون شبیه به استک شما بوده و دوست داشتید که در فیلدی که دارن کار می‌کنن کار کنین. لطفا خیلی دروغ نگید این بخش رو، ولی داستان هم نبافید که توی ایران ملت رو دارن رندوم با گلوله تو خیابون می‌زنن و هر بار که میرید تو خیابون ممکنه به یه دلیلی کشته بشید و قاتلتون زیر تابوتتون رو بگیره. هدفتون رو تکنیکال بگید لطفا و روراست. رستم نشون ندید خودتون رو. کلی ایرانی‌ دیگه مثل من و شما میخوان این فرایند رو دنبال بکنن و شما فقط معرف خودتون نیستید، معرف کامیونتی دولوپر‌های ایران هستید که هزار هزار دارن سعی می‌کنن برن بیرون از ایران.سوالات بعدی سوالات عمومی هستن مثل تجارب کاری دیگه، علاقمندی‌ها بیرون از کار. من مشخصا می‌گردم توی لینکداین و گلسدور و با فرهنگشون اشنا می‌شم و اگر باهام برابر بود سیستمشون، میگم که علاقمند به کوه‌نوردی و پیاده روی و دوچرخه سواری هستم. اگر دیدید که این مدل شرکتی نیستن، یه چیزی ببافید خلاصه. ولی فرهنگ کشور مقصد رو در نظر بگیرید. مثلا برای کشوری که ۴طرفش خشکیه اقیانوس گردی و اینا یا کشوری که کلا مرتفع‌ترین جاش برج مخابراتی سر میدون امامشون هست، عاشق  کوه‌نوردی رو نگید بهتره! به نظرم :)مصاحبه تکنیکال اولیهاین مصاحبه، بسته به شرکت مقصد که از این کوچیکا باشه یا شرکت‌های کاملا شناخته شده مثل امازون و ردهت و امثالهم متفاوت میشه. منابع خیلی زیادی هست که میگه توی تکنیکال اینترویو تلفنی! با امازون یا فیس بوک یا رد‌هت، انتظار چه تایپ سوالاتی رو باید داشته باشید.توی شرکت‌های کوچیک‌تر ازتون سوالات راحت‌تری می‌پرسن. مثلا ازتون می‌خوان که دوتا لیست رو مرج و سورت کنین یا دوتا لیست رو میدین‌اش رو به دست بیارید. یا یه سری سوالات ریز الگوریتمی این مدلی.تجربه شخصی من این بوده که شرکت‌های کوچیک ازتون میخوان به جواب برسید فقط. گاهی وقتا شخصا حتی با نشون دادن اینکه میدونم باید چیکار کرد ولی کدش رو ننوشتم اوکی بودن باهام.ولی مثلا امازون ازتون می‌خواد که یه راه‌حل لینیر (O(n)) بهش بدید برای مسئله و کارتون کمی سخت تره.در هر دو مورد، مهم‌تر از خود جواب، فک کردنتون هست. خیلی مهمه که بلند بلند فک کنین. مثلا دارید فکر میکنین هم، این سوال رو دوتا لوپ می‌زنم یه پوینتر از اول لیست شروع کنه یکی از اخر شروع کنه و مقایسه می‌کنم بعد میگید فاک‌ایت! اینکه O(n^2) هستش به درد نمی‌خوره. اینو تو ذهنتون نگید. اینو بلند بلند بگید که طرف بشنوه. بلند بلند فک کردن بازم می‌گم از خود نوشتن جواب مهم‌تره و به طرف نشون بدید چطوری به یه مسئله حمله می‌کنین. هم شما می‌دونید هم اونا می‌دونن شما تو ۱۰ ثانیه تو استک‌اورفلو می‌تونید جوابش رو پیدا کنین و بزنین. ولی سیستم فکر کردن ادما و اینکه چی سرچ کنن چیزیه که اونا میخوان. پس بلند بلند فک کنین، بلند اشتباه کنین و اشتباهتون رو کشف کنین و بگید و حلش کنین. دیزاینتون رو بگید بلند بلند...کدینگ اینترویواین مصاحبه، من خودم باهاش خیلی درگیر بودم. ۳ تا از این مصاحبه‌ها داشتم. چیزی که من نتیجه گرفتم و با بقیه صحبت کردم اینه که استانداردی نداره. تجربه شخصیم این بوده که یه پروژه میدن، خیلی ریز و میگن خوب حلش کن. اونا شما رو در حال کد زدن نگاه می‌کنن(کلی پلتفرم برای این‌کار هست سعی کنین باهاشون اشنا باشید، مثلا repl.it یا codeshare.io که در اولی، اونا کد شما رو می‌بینن، در دومی در لحظه و زنده می‌بینن دارید چیکار می‌کنید. دومی به قولی لایو‌تره :)مسئله بسته به جایی که توش کار می‌کنین متفاوته. یه جا ممکنه بهتون بگن یه لیست درست کن که اگر مثلا خواستم یه مقداری رو از لیست برگردونیم و نداشتش، به جای ارور keyErro یا چیزی مثل اون، None برگردونه. لازمه که شما کد زدن بلد باشید و اشنا باشید که بتونید حل کنین.وات د فاز؟دقیقا! اولین باری که یکی ازم پرسید اوکی این لیست رو سورت کن، بهش گفتم ایزی پیزی t.sorted() و یارو چند لحظه برگاش رو جمع کرد و گفت نه حاجی بنویس کدی که sorted داره اجرا می‌کنه!!بریید به سایتهای hackerrank و leetcode لاگین کنین و شروع کنین مسئله‌هاشون رو حل کنین. سعی کنین تابع پایتونی فراخونی نکنین و همش رو خودتون بنویسید.من توی یه مصاحبه(ایران) ازم خواسته شد که یه ارایه دو بعدی رو بچرخم و عددی رو پیدا کنم که تو سطر‌ها کمترین و توی ستون‌ها بیشترین باشه. با خودم گفتم ایول شغل رو گرفتم(فقط دو سوال می‌پرسیدن!) سریع نوشتم که خوب min=min(given_array) و طرف گفت min دیگه کیه؟ برام بنویس که minچطوری کار میکنه. یه خورده نیگا کردم و فرمت شدم. هر کاری کردم نتونستم ذهنم رو برگردونم. می‌ترسیدم به عنوان یه دولوپر با ۲ سال سابقه، بیام لوپ بزنم و min رو به روش دانشگاهی بنویسمش!! هرچی مصاحبه گر تلاش کرد حاضر نشدم خفت اینکه احمق‌تر به نظر برسم رو قبول کنم و بنویسمش... بعد از چند روز دیدم کلا همون راه بوده و باید همونجوری می‌رفتم. حتی به خود مصاحبه گر پیام دادم که داداش این راه‌حلش همین بود؟ اونم گفت اره... هنوز وقتی چهره اون رو یادم میاد که داشت تلاش می‌کرد که منو بگردونه یادمه. فقط میخواستم بیام بیرون از مصاحبه... دلیلش؟ این مدل سوال رو ندیده بودم و امادگی این رو نداشتم که ۵۰ خط کد بنویسم که در حالت عادی ۵ خط کده. فکر می‌کردم باید همچنان ۵ خط کد بنویسم براش ولی بلدش نیستم...سوالات هکررنک و لیت‌کد رو رنده کنین. وقتی فکر می‌کنین منظورش همون باینری سورت احمقانه دانشگاهه واقعا؟ یعنی بیام بنویسم if min &lt; num؟ اره دقیقا فاکینگ همین رو میخوان. امازون و گوگلش دقیقا همین رو میخوان... چشمتون باید بهش عادت کنه، دستتون باید بهش عادت کنه که بنویسیدش...توی کداینترویو گاهی اوقات مسئله یا اینترویویر بهتون اجازه میده از توابع اماده استفاده کنین و ازتون میخوان کد نرمال و روزمره براشون بنویسید. تر و تمیز بنویسید، همهٔ جوانب رو در نظر بگیرید و خلاصه سعی کنین یه دفعه کدتون ۱۵ تا x,y, a,b,c,i,j نیوفته توش که هیچکس نفهمه چی به چیه.اسم تابع برعکس کننده متنتون باید reverse باشه یا این کلمه توش باشه! لیستی که اعداد اول رو توش می‌ریزید اسمش a نباشه مثلا odd_nums یا even_nums باشه(این دوتایی که نوشتم زوج و فرد بودن البته!)مسئله اینه که حتما سوال کنین و حتما حرف بزنین. عشقی در نظر نگیرید که اوکی لیستی که بهم میدن سورت شدست فلان کارو می‌کنم. بپرسید! برندارید بدون چک عدد رو تقسیم کنین.:) یه صفر بندازن وسط یا جای عدد متن بندازن وسط به فنا میره کد!این چیزا رو چک کنین یا بپرسید ازشون یا بگید که فعلا نگران اونا نیستید.راستی، ۹۸.۹ درصد اوقات، توی یه تکست‌ادیتور می‌نویسید. خیلی بهتون لطف کنین سینتکس‌هایلایت دارید! اگر مثل من هستید که یادتون نیست چطوری به کیو توی پایتون عدد اضافه میشه، بگید که اهم یادم نیست فک کنم فلانه و حالا تست می‌کنم ببینم چی میشه:) یا از قبل یه یاداوری بکنین این چیزا رو. من سر هش‌ست(set) پیاتون گیر کردم که چطوری میشه چک کرد عددی داخلشه یا نه! :)خلاصه یا ازتون میخوان تمیز کد بزنین و کد معمولی بزنین که به این نکات توش توجه کنین و اگر ازتون سوالات الگوریتمیک پرسیدن، you already know what to doسیستم دیزاین؟این مصاحبه رو من توی شرکت‌های بزرگ دیدم. شرکتی مثل گوگل یا توییتر یه تیم ۲۰ نفره مهندسین رو داره که ۶ ماه وقت می‌ذارن تا سرویس نایت‌هاوک رو دیپلوی کنن که وظیفه کنترل کشینگ پروفایل‌ها توی توییتر باشه، ولی مصاحبه گر از شما می‌خواد که تو ۱۵ دقیقه همین سیستم رو براش دیزاین و اسکیل کنین:) بنابراین باید از قبل اماده باشید که بتونید در موردش حرف بزنید و یا یه سیستم کوچیک رو خیلی سریع دیزاین کنین. کجا کش میذارید، کجا لود بالانسر می‌ذارید، کجا دیتابیس میذارید و این صحبتا.یه سری کانال یوتوبی خوب هستش که می‌تونید دنبال کنید(یک و دو) و توضیح میدن سیستم دیزاین یه محصول رو. شخصا فقط یه بار با همچین چیزی درگیر شدم و خوب موفق هم نشدم چون اولین باری بود که می‌دیدمش.مصاحبه دیگه؟بعضی شرکتا قبل از تکنیکال اینترویو و بعد از مصاحبه اچ‌ار، یا حین همون مصاحبه اولیه اچ‌ار، یه سری سوالات ممکنه بپرسن که خیلی کلیه. مثلا فرق مولتی‌پراسس با مولتی‌ترد چیه؟ کِی از کدوم باید استفاده کنیم؟ یا دیکشنری/هش‌مپ(تقریبا!) با لیست فرقش چیه و چیزایی مثل اینها. خوبه که یه سری جواب از قبل واسه اینها اماده داشته باشید. یا مثلا  ممکنه بهتون یه دفعه برگرده بگه میشه یه توپل رو به عنوان کلید یه دیکشنری استفاده کرد؟ بهتره که از قبل با این چیزا اشنایی کوچولویی داشته باشید.همچنین توی کدینگ اینترویو یا اچ‌ار ازتون بخوان که مثلا روش کار کردنتون توی شرکت رو بگید.مثلا تسک‌ها چطوری میاد، کی تصمیم می‌گیره که کدوم کار اولویت بالاتری داره، گیت فلوتون توی شرکت چیه و چیزای مثل اینا. خوبه که بتونین از قبل جوابهایی برای این تیپ سوالا داشته باشید که بدون تپق بگیدشون.گاهی اوقات، جلوی شما یه بابایی نشسته که مثلا داکر رو خورده، بعد شما یه تجربه ریزی دارید و میگید اره داکر رو بلدم. بعد یارو یه سوال دیپ می‌پرسه و می‌ترکوندتون. استراتژی من برای وقتی که می‌پرسن با فلان تکنولوژی کار کردی؟ همیشه این هستش که آره، باهاش فلان کار رو کردم فقط ولی خیلی درگیر نبودم.مثلا من لینکداین یه بابایی رو چک کردم، طرف تیم لیده و البته ELK اشون رو هم هندل می‌کنه، توی صحبتام یه لحظه از دهنم می‌افته که ELK درگیر بودم یه کم، وقتی طرف که توی دولوپ حرفی نداشت برای گفتن میخواد اینجا مچم رو بگیره و ازم در موردش می‌پرسه، منی که با این استک ۶ ماه پیش یه حرکتی زدم نمیام بگم من پدر الستیک ایرانم! قشنگ و کامل توضیح میدم که یه مشتری یه چیزی ازمون میخواست و من براشون هندل کردم، نه دروغ گفتم، نه خودمو گیر میندازم که سوالات بعدی الستیکی بیاد سمتم، نه خراب میشم توی مصاحبه.هوم اساینمنتبه صورت معمول، من بین مصاحبه تکنیکال و کدینگم یه پروژه هم گرفتم که روش کار کنم. این پروژه ها سبک، سریع و تخصصی هستن. معمولا شما رو حسابی درگیر میکنن توی یه قضیه‌ای.بر اساس تجربه، تمیز نوشتنش، تست نوشتن، داکیومنت کردنش و نهایتا فاکنیگ توضیح دادن استفاده از کد مورد توجه قرار می‌گیره. اسم‌هایی که برای کامیت‌هایتون میذارید و چیزایی که با هر کامیت میره بالا هم حواستون باشه به قولی  تست‌های فایل a و کدهای فایل b با کامیت مسیج &quot;working code&quot; نفرستید بالا سر جدتون :)خوب، شرکت‌های بزرگ تازه ممکنه بهتون اوکی بدن که برید محل شرکت و همین مصاحبه‌ها رو خیلی جدی‌تر و ۱-۲ ساعتی دوباره ازتون بگیرن با سوالات دیگه. توی اینترنت نحوه اماده شدن برای مصاحبه امازون و گوگل و بوکینگ و امثالهم ریخته.شرکت‌های کوچیک هم که دیگه احتمالا بهتون افر میدن و میرید توی پروسه ویزا و رفتن به اونجا.دو سالی هست که وبلاگ ننوشتم و ببخشید بابت مدل نوشتنم!</description>
                <category>Maysam senaps</category>
                <author>Maysam senaps</author>
                <pubDate>Thu, 30 Jan 2020 19:52:09 +0330</pubDate>
            </item>
                    <item>
                <title>آدرس فایل‌ها در پایتون، وقتی پکیج می‌شوند</title>
                <link>https://virgool.io/@senaps/%D8%A2%D8%AF%D8%B1%D8%B3-%D9%81%D8%A7%DB%8C%D9%84%D9%87%D8%A7-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-%D9%88%D9%82%D8%AA%DB%8C-%D9%BE%DA%A9%DB%8C%D8%AC-%D9%85%DB%8C%D8%B4%D9%88%D9%86%D8%AF-gkl79dfnkxv5</link>
                <description>تیتر سوال خیلی عجیبه قبول دارم!من امروز داشتم برای خودم یه مقدار کد می‌نوشتم، توی بخشی از کدم لازم بود تا از پوشه‌ای به اسم /templates یک پوشه‌ای رو کپی بکنم. پر واضحه که توی پایتون باید از پت‌های ابسلوت به شکل درست‌اش استفاده کرد تا وقتی کد رو به جای دیگه‌ای منتقل می‌کنیم، همچنان درست کار بکنه و ادرس‌ها درست کار بکنه. کلیت کد من یه همچین چیزی بود:TEMPLATE_PATH = os.path.join(os.path.abspath(&amp;quot.&amp;quot), &amp;quottemplates/&amp;quot)این کد، ادرس فعلی جایی که کد رو فراخوانی کردیم رو میاره، اسم /templates رو میذاره اخرش و یه پت درست بهمون میده. کد در حالت عادی که باهاش کار می‌کردم کار می‌کرد، ولی وقتی داشتم براش تست می‌نوشتم و کد رو از جای دیگه‌ای اجرا می‌کردم، متوجه شدم که ارور می‌گیره کد. در حقیقت مشکل این بود که کد بالا، در صورتی که خود فایلی که کد درش قرار داره اجرا بشه درست کار میکنه و در باقی موارد(مثلا ایمپورت کردن این فایل در یک ماژول دیگه) دیگه درست کار نخواهد کرد.مثلا من ماژولی که این کد درش قرار داشت رو از یک پوشه قبل‌تر نتونستم درست صدا بزنم و بعد که این مشکل رو حل کردم، متوجه شدم که مشکل از این هم بیشتره!اگر کد بالا رو پکیج کنیم و نصبش کنیم و بعد بخوایم از هرجایی که دلمون میخواد صداش بزنیم، اتفاقی که می‌افته این هستش که بخش اول تابع یعنی (os.path.abspath) شروع میکنه به برگردوندن ادرس جایی که الان درش هستیم. و جایی که درش هستیم دیگه پوشه templates کنار دستش نیست که اونها رو لود بکنه!برای حل این مشکل، پایتون کلی راه‌حل تر و تمیز و حرفه‌ای داره. از importlib گرفته که از پایتون ۳.۷ به استاندارد لایبرری استفاده شده تا pathlib (باز هم در استاندارد لایبرری).مشکل اینه که هر کدوم از این راه‌حل ها یا برای ورژن بخصوصی از پایتون بودن یا اینکه نیاز داشتن تا کلی کار بکنیم که بتونیم یه پت ساده رو ست بکنیم.distutils.errors.DistutilsFileError: cannot copy tree &#039;/home/senaps/Projects/python/sfgen/code/templates/simple_app&#039;: not a directory
همینجور که می‌بینید، ادرس به صورت کلی از کار افتاده و ادرس در حقیقت باید به همچین فرمتی ساخته می‌شد:/home/senaps/Projects/python/sfgen/code/sfgen/templates/simple_appدر حقیقت بخاطر اینکه من از داخل پوشه sfgen کد رو تست می‌کردم و حالا برای نصب و اجرای تست‌های اتوماتیکم از داخل پوشه code تست‌ها رو اجرا می‌کردم، دیگه نمی‌تونست درست محل رو پیدا بکنه. اگر هم که بعد از نصب، از مثلا /home اجرا می‌کردم کد رو، ادرس به کلی نابود می‌شد و مثلا همچین فرمتی در می‌اومد:/home/senaps/templates/simple_appهمونجور که گفتم، راه‌حل های مختلفی برای حل این مشکل هست، ولی من به عنوان یه برنامه‌نیوسی که واقعا حوصله ندارم روش‌های درست رو یاد بگیرم، اومدم و دور زدم مشکل رو. راه‌حل درست مورد نظر من، راه‌حلی بود که بتونه تست‌های لوکال خودم (وقتی که خود فایل cli.py رو اجرا می‌کنم از داخل پوشه sfgen) رو هندل کنه، هم تست‌ها رو پاس کنه و هم بعد از نصب همچنان درست کار کنه! بنابراین اومدم تغییر رو به این صورت اعمال کردم:if __name__ == &amp;quot__main__&amp;quot:
    curr_path = os.path.abspath(&amp;quot.&amp;quot)
else:
    curr_path = os.path.abspath(__file__)[:-7]
TEMPLATES_PATH = os.path.join(curr_path, &amp;quottemplates/&amp;quot)خوب، چیکار کردیم؟اول اومدم بررسی کردم که آیا کد رو دارم مستقیم صدا میزنم یا اینکه از جای دیگه‌ای داره صدا زده میشه؟ اگر خودم مستقیم کد رو صدا زدم که کلا مشکل هست هست و میریم برای ادامه زندگی‌مون.اما اگر غیر از اینه، ابتدا میایم ابسلوت پت فایلی که اجرا شده رو میگیریم.curr_path = os.path.abspath(__file__)
/home/senaps/Projects/python/sfgen/code/sfgen/cli.pyاین ادرسی که بهمون داده رو ما بخش اخرش رو نمی‌خوایم! یعنی همین ادرس منهای &#x60;/cli.py&#x60; واقعا کار ما رو راه می‌ندازه. بنابراین به صورت هارد‌کدی با اسلایس کردنش ‍&#x60;[:-7]&#x60; مشخص می‌کنیم که کل استرینگ رو غیر از ۷ کاراکتر اخر بهمون بده.در نهایت با استفاده از تابع جوین‌پت، پت‌های گرفته شده رو به هم وصل می‌کنیم و برنامه اوکی پیش خواهد رفت بدون مشکل.نکته این هستش که من توی این کد دوبار شرط ‍‍&#x60;if __name__ == &quot;__main__&quot;:&#x60;  رو استفاده کردم. یکبار در بالای کد برای این بخش از ساختن ادرس‌ها، و یکبار در پایین کد برای مشخص کردن روال برنامه.شما راه‌حل بهتری سراغ دارید برای این مشکل؟ ممنون می‌شم که بهم بگید :)این‌هم کد نهایی در اینجا که یکی از پروژه‌هایی هستش که رسما روال یادگیری پایتون من رو تا اینجا نمایندگی میکنه :)</description>
                <category>Maysam senaps</category>
                <author>Maysam senaps</author>
                <pubDate>Thu, 19 Dec 2019 22:17:23 +0330</pubDate>
            </item>
                    <item>
                <title>لود داینامیک فایلها و اپلیکیشن‌ها در پایتون و فلسک</title>
                <link>https://virgool.io/pullrequest/%D9%84%D9%88%D8%AF-%D8%AF%D8%A7%DB%8C%D9%86%D8%A7%D9%85%DB%8C%DA%A9-%D9%81%D8%A7%DB%8C%D9%84%D9%87%D8%A7-%D9%88-%D8%A7%D9%BE%D9%84%DB%8C%DA%A9%DB%8C%D8%B4%D9%86%D9%87%D8%A7-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-%D9%88-%D9%81%D9%84%D8%B3%DA%A9-zvio1hja3k6i</link>
                <description>سلام.در فلسک یه کانسپت بخصوص به نام بلوپرینت(Blueprint) وجود داره که اجازه میده ما بتونیم بخش‌های مختلف اپلیکیشن رو، از همدیگه تفکیک بکنیم. اگر با جنگو آشنا باشید، بلوپرینت‌ها همون ‍&#x60;اپ&#x60; های جنگو هستن.حالا، اخیرا نیاز شده بود که به صورت داینامیک یه اپلیکیشن به پروژه اضافه بشه یا ازش برداشته بشه و میخواستیم این کار به ساده‌ترین صورت ممکن قابل انجام باشه. از بین کل‌ راه‌های موجود برای این‌کار، کپی کردن فایل به محلی مشخص و لود شدن بلو‌پرینت و ریجستر شدنش به صورت اتوماتیک رو انتخاب کردیم.با فلسک، پایتونی کد میزنیم!نکتهٔ خیلی مهم در مورد فلسک، این هستش که بر خلاف جنگو، شما پایتون کد می‌زنید. در واقع، برای اینکه بتونید با جنگو کار کنید، باید یاد بگیرید که هر کاری رو توی جنگو به چه صورت انجام می‌دن. ولی این در مورد فلسک صدق نمی‌کنه. فلسک اونقدر کوچیکه و بدون پیش‌فرض در مورد کد شما، که برای کار کردن باهاش، کافیه بلد باشید اون کار رو توی پایتون چطوری باید انجام داد. باقی قضیه دیزاین و توانایی خودتون هست. این قضیه در عین حال که سادگی بیش‌از اندازه فلسک رو به همراه داره، ساختن اپلیکیشن پروداکشن رو باهاش به شدت سخت می‌کنه. شما مسئول همه چیز هستید و هیچ کاری برای شما انجام نمیشه.انجام نرمال کارهااول، میگم‌که ساختار پروژه‌ام چطوری هستش و فایل‌ها رو چطوری کنار هم می‌چینم و بلو‌پرینت درست می‌کنم، بعدش لود داینامیک اونها رو بررسی می‌کنم.من نیاز دارم که یه پروژه فلسک که بلوپرینت ساپورت می‌کنه بسازم. کل فایل‌هایی که باید بسازم به صورت زیر هستش├── develop.py
├── dloader
│   ├── application.py
│   ├── apps
│   │   ├── __init__.py
│   │   └── test_app
│   │       ├── __init__.py
│   │       └── views.py
│   ├── __init__.py
└── README.mdکدهایی که باید داخل این فایل‌ها بره رو از توی گیت میتونید بردارید. من تمام فایل‌ها رو بررسی نمی‌کنم!کد‌های فایل application.py به صورت زیر هستنfrom flask import Flask

def create_app():
    app = Flask(__name__)
    _load_blueprints(app)
    return app
    
def _load_blueprints(app):
     from .apps.test_app import test
      app.register_blueprint(test)همچنین برای ساختن بلو‌پرینت‌ در فایل init.py به صورت زیر عمل کردم(فایل داخل پوشه apps)from flask import Blueprint
test = Blueprint(&#039;test&#039;, __name__)در صورت اجرا، این‌ کدها به درستی عمل میکنند. حالا میخوایم به صورت داینامیک بلو‌پرینت‌ها رو لود کنیم. تغییرات چندان زیادی لازم نیست. همچنین میشه به صورت های مختلفی این‌کار رو انجام داد. من در نهایت از روشی استفاده کردم که در ادامه توضیحش می‌دم اما کاملا به فکر هستم که سیستم‌اش رو عوض کنم.من فایل application.py رو به صورت زیر ویرایش میکنمimport importlib
import os

 def _load_blueprints(app):
    folder_names =  os.listdir(&quot;dloader/apps/&quot;)
    for name in folder_names:
        if name.endswith(&quot;_app&quot;):
            tmp_blueprint = importlib.import_module(f&quot;.{name}&quot;, &quot;dloader.apps&quot;)
            app.register_blueprint(tmp_blueprint.blueprint)اول از همه کل‌پوشه‌های داخل مسیر رو به دست اوردم، بعد از اون روی لیست پوشه‌ها لوپ زدم. در مرحله بعد بررسی کردم که اگر اسم پوشه به app_ ختم میشه، بنابراین جزو بلوپرینت های من هستش. اون رو ایمپورت کردم و بعد هم ریجستر.این وسط یه اتفاقی افتاده و اون خط اخر هستش. همینجوری که می‌بینید من از ماژول ایمپورت شده، دارم متغییری به نام blueprint رو استفاده می‌کنم. دلیل این قضیه این هستش که من با ایمپورتی که در خط قبلی انجام دادم، نیاز دارم به خود ابجکت بلوپرینت اشاره کنم تا بتونم ریجسترش کنم.حالا برای اینکه اسم بلوپرینت هم داینامیک باشه، من همیشه ابجکت بلوپرینت رو باید داخل یه متغییر به اسم blueprint گذاشته باشم:)فایل init ام به صورت زیر تغییر میکنه بنابراینtest = Blueprint(&#039;test&#039;, __name__)
blueprint = testهمینجور که می‌بینید، من در نهایت ابجکت blueprint رو برای ریجستر کردن استفاده کردم.همچنین در صورتی که بخوام url_prefix استفاده کنم هم می‌تونم به همین صورت یه متغییر بهش بایند کنم و استفاده‌اش کنم.این importlib چیکار میکنهماژول importlib برای ایمپورت کردن پکیج‌ها و ماژول‌های مختلف به صورت داینامیک و از داخل کد هستش. همینجور که می‌بینید ما از یه کد کاملا پایتونی برای انجام این‌کار در فلسک استفاده کردیم.این تابع دوتا ارگومنت می‌گیره که البته دومی الزامی نیست. بر اساس داکیومنت پایتونThe &#x27;package&#x27; argument is required when performing a relative import. It specifies the package to use as the anchor point from which to resolve the relative import to an absolute import.بنابراین فقط در صورتی که داریم رلتیو ایمپورت انجام می‌دیم، نیاز هستش که از package استفاده کنیم. همچنین بهتره که با یه . شروع کنیم اسم ماژولی که باید ایمپورت بشه تا به مشکل نخوریم! :)این ماژول واقعا کار راه انداز هستش و مشخصا بهتون کمک می‌کنه که به صورت داینامیک و راحت، با استفاده از کد ماژول‌های مختلف رو ایمپورت کنین و نه اینکه همیشه همه چیز رو ایمپورت کنین. همچنین میشه به صورت کلی به عنوان یه پلاگین سیستم و لودر اتوماتیک پلاگین‌ها هم بهش نگاه کرد.کد کامل پروژه که کار میکنه رو براتون اینجا اپلود کردم که میتونید استفاده کنین.</description>
                <category>Maysam senaps</category>
                <author>Maysam senaps</author>
                <pubDate>Thu, 07 Feb 2019 22:22:13 +0330</pubDate>
            </item>
                    <item>
                <title>استفاده از celery و sqalchemy با فکتوری‌های فلسک</title>
                <link>https://virgool.io/pullrequest/%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-celery-%D9%88-sqalchemy-%D8%A8%D8%A7-%D9%81%DA%A9%D8%AA%D9%88%D8%B1%DB%8C%D9%87%D8%A7%DB%8C-%D9%81%D9%84%D8%B3%DA%A9-podigdbcr90u</link>
                <description>فلسک یه میکروفریم‌ورک بسیار جذاب و باحاله. مهم‌ترین چیز در موردش این هست که می‌تونی به سادگی چیزی که میخوای رو به سرعت باهاش تولید کنی، و هیچ کد اضافی‌ای داخلش نیست. همه چیز به همون شکل و فرم‌ای هست که خودت میخوای.الزامی نیست که حتما پروژه رو به فلان شکل بخصوص بسازی. متودولوژی‌ها و غیره و ذلک همه به خود شخص بستگی داره.این قضیه، هم خوبه و هم بد. خیلی بد و ترسناکه چون اگر ندونی که داری چیکار میکنی، ممکنه به صورت جد به مشکل بخوری و نتونی محصولی تولید کنی.در ادامه، شما حتما با celery  هم آشنا هستید. اگر نه، خیلی خلاصه براتون به این صورت بگم که یه پراسس هست که شما کارهایی که طول می‌کشه رو بهش میدید تا براتون انجام بده، بدون اینکه برنامتون درگیر بشه. یه مثال بعدا براتون می‌زنم که دقیقا بدونید جریان چیه و منظورمون چیه.در نهایت، sqlalchemy هم یه orm هستش که ازش استفاده می‌کنیم تا کار کردن با دیتابیس برامون راحت‌تر و به صورت ابجکت‌اورینتد باشه، امن‌تر باشه و نیاز نباشه کوری بنویسیم. خلاصه کلی کاربرد که بهتره همینجا ببندیمش و درگیرش نشیم بیشتر!نکته: این مطلب برای کسانی‌هست که با همهٔ موارد بلدن کار بکنن و فقط داره این شیوهٔ بخصوص استفاده از اونها در کنار هم رو بررسی می‌کنه و به هیچ عنوان به عنوان آموزش اولیه کاربرد نداره.اکسپورت ریپورت!برای پروژهٔ شرکت، نیاز هستش که یه سیستم ریپورتر داشته باشیم. کاربر بتونه گزارش‌های مختلف رو ببینه و دسته‌بندی کنه و چیزهای مثل اون. خوب، طبیعی هستش که یکی از نیازهایی که همراه همچین چیزی پیش میاد، امکان اکسپورت کردن(Export) یا دانلود کل گزارش در یک فایل هستش.پروژهٔ ما گاها حتی تا چند میلیون خط هم گزارش باید جنریت میکرد و کوری‌های سنگینی باید اجرا می‌شد. بنابراین ممکن بود شما بعد از کلیک روی لینک اکسپورت، مجبور باشید ۱۰-۱۲ ثانیه منتظر باشید یا حتی ممکن بود با ارور ۵۰۲ بخورید. مسئله این هست که این کار طول می‌کشه و احمقانه‌ست که کاربر رو منتظر بذاریم تا بخواد بیاد نتیجه رو ببینه.کاری که می‌کنیم این هست که دستور اکسپورت رو می‌گیریم، سریعا به کاربر اطلاع می‌دیم که افتادیم دنبال کارهاش و بعدا میتونه سر بزنه ببینه وضعیت گزارش مد نظرش چی هست یا اینکه خودمون بهش ایمیلی چیزی بزنیم و خبرش کنیم که کارش انجام شده.در عین حال، درخواست کاربر رو به سلری می‌دیم تا کار رو برامون انجام بده.امروز، بعد از حدود دو ماه از تعریف این پروژه و برنامه ریزی، تسک انجام این کار به من داده شد. نیاز بود که در بستر فلسک و sqlalchemy، من سلری رو اجرا کنم و تسک‌ها رو به سیستم بدم تا برام انجام بده.انجام تسکنترسید!نمی‌خوام خط به خط و ریز به ریز توضیح بدم که چیکار کردم! به نوشتن کلیت کاری که صورت گرفته تا پروژه به درستی کار کنه بسنده می‌کنم و امیدوارم که بتونه مشکلی از کسی حل کنه و کمی بندازتش جلو.ساختار فعلی پروژه├── deploy.py
├── __init__.py
└── project
├── application.py
├── apps
│   ├── auth
│   │   └── __init__.py
│   ├── __init__.py
│   └── report
│       ├── __init__.py
│       ├── models.py
│       └── views.py
├── config.py
├── extensions.py
    └── __init__.pyتوی چند خط خیلی سریع توضیح می‌دم که هر کدوم از این فایل‌ها چیکار میکننفایل deploy فایلی هستش که برای اجرای اپ فلسک ازش استفاده می‌کنیم. application فایلی هست که تابع‌های مورد نیاز برای ساختن یه اپ flask توش قرار داره. به قول معروف تابع &#x60;create_app&#x60; اینجاست. فایل extensions که شامل پلاگین‌هایی هستش که برای فلسک نصب کردیم. پوشهٔ apps هم شامل app هایی هستش که توی اپلیکیشن وجود دارن. بعدا در موردشون بیشتر حرف می‌زنیم. نهایتا فایلی config جایی هست که تنظیمات اپلیکیشن درش قرار دارند.این پروژه به خودی خود کار می‌کنه و مشکلی نداره.ساخت ورکر و تسک‌هااولین ادیت به فایل extensions اضافه می‌شهfrom celery import Celery  
celery = Celery() ابجکت رو خام اینجا می‌سازیم تا درگیر circular import نشیم. بعدا می‌بینید کاربردش رو.حالا باید بریم داخل فایل application و کدهای زیر رو اضافه می‌کنیمdef create_celery(app):
    celery.config_from_object(app.config)
     return celeryابجکت اینجوری کار می‌کنه که ما هر وقت می‌خوایم یه ورکر سلری رو استفاده کنیم، این تابع رو صدا می‌زنیم و ازش استفاده می‌کنیم. بنابراین میشه با یه کد، چندین اینستنس مختلف با تنظیمات مختلف رو اجرا کرد، بدون اینکه نیازی باشه کدهای ساخت سلری رو عوض کنیم.قبل از اینکه بریم فایل ورکر رو بسازیم، نیاز هست که یه سری تنظیمات برای سلری به فایل config اضافه کنیم. سلری برای کار کردنش، نیاز به یه روشی داره که بتونه پیام‌ها رو از ما بگیره و نتیجه‌اش رو بهمون برگردونه. برای اینکار باید از یه مسیج‌کیو (message queue) استفاده بشه. بعضی‌های ردیس استفاده میکنن ولی من ربیت(rabbitmq) استفاده کردم. دلیل هم این هست که توی این پروژهٔ بخصوص ما، جاهای دیگه‌ای داریم از ربیت استفاده میکنیم و از قبل نصب هست. پس میشه ازش استفاده کرد بدون مشکل.توی فایل config باید چیزی اضافه بشه. ساختار این برای من به صورت کلاس‌های مختلف برای محیط های مختلف هستش. ProductionConfig برای محیط پروداکشن، DevelopmentConfig برای وقتی که دارم دولوپ می‌کنم و... تمام این‌کلاس‌ها یه سری دیتای مشترک با هم دارن که توی یه کلاس به اسم DefaultConfigs قرار دارن و کلاس‌های کانفیگ پروداکشن، دولوپ، تست و ... از اون ارث‌بردن. بنابراین با خیال راحت تنظیمات رو توی همین کلاس دیفالت اضافه میکنم که همه داشته باشنشون. class DefaultConfigs: 
    ...
    CELERY_BROKER_URL = &quot;amqp://localhost/&quot;
    CELERY_RESULT_BACKEND = &quot;rpc://&quot;تو خط اول، داریم ادرس بروکر رو بهش میدیم که اینجا ربیت‌هستش و دومین، ادرس جایی هست که نتیجه عملیات‌ها توش ذخیره خواهند شد! میتونه یه دیتابیس باشه یا هرچیزی. اینجا من فعلا درگیر این قضیه نمی‌شم.حالا باید بریم یه ورکر بسازیم که بتونه اجرا بشه.توی دایرکتوری روت پروژه و کنار deploy ام یه فایل درست می‌کنم به اسم worker.py و کدهای زیر رو داخلش می‌نویسم:from project.application import create_app, create_celery
from project.config import ProductionConfig

app = create_app(ProductionConfig)
celery = create_celery(app)

with app.app_context():
    celery.start()توی خط اول، داریم توابع فکتوری رو ایمپورت می‌کنیم. این توابع رو نیاز داریم تا بتونیم ابجکت‌های سلری و فلسک رو باهاشون بسازیم.خط دوم داریم کانفیگ پروداکشن رو ایمپورت می‌کنیم. دو خط بعدی دارن با استفاده از توابع فکتوری، دوتا ابجکت فلسک و سلری می‌سازن. می‌بینید که کاملا توابع می‌تونن به سادگی و فقط با پاس دادن یه کانفیگ دیگه، یا اپلیکیشن دیگه، کاملا رفتارشون عوض بشه و این زیبایی استفاده از فکتوری‌هاست.در نهایت، چون میخوایم از دیتابیس‌ها استفاده کنیم، و دیتابیس ها توی کانتکست فلسک فقط درست کار میکنن، تابع celery.start رو داخل کانتکست فلسک‌مون اجرا می‌کنیم.خوب، تبریک می‌گم! مراحل راه‌اندازی سلری و فلسک به پایان رسید. شما می‌تونید برید و تسک‌هاتون رو اضافه کنین.من توی پوشه project ام، یه دایرکتوری دارم به اسم utils که داخلش کدهایی که استفاده می‌کنم هستن. یه فایل tasks.py توی این پوشه درست میکنم و کدهای زیر رو توش می‌نویسمfrom project.extensions import db, celeryهمینجور که می‌بینید، رفتم از فایل extensions ابجکت سلری و دیتابیس رو ایمپورت کردم. (ابجکت db هم دقیقا به همون شکلی اونجا ساخته شده که ابجکت سلری ساخته شده)حالا، باید مدل‌هام رو از داخل اپ‌هام ایمپورت کنم به داخل این فایل تا بتونم استفاده‌شون بکنمfrom project.extensions import db, celery
from project.apps.report.models import Namesحالا باید کدها و توابع‌ام رو بنویسم.@celery.task(name=&quot;cl_get_names&quot;)
def get_names():
    names = Names.query.all()
    return [x.name for x in names]در کد بالا، با یه دکوریتور یه تسک درست می‌کنیم. ارگویمنت name برای این هست که سلری با این اسم بشناستش و اگر احتمالا توی کد‌هام جای دیگه‌ای همین تابع رو استفاده کرده بودم، قاطی پاتی نشه چیزا. همچنین من سعی می‌کنم اسمی که برای تسک‌هام میذارم از بیرون قابل فهم باشه. مثلا دو حرف اول اسم تسک رو از اسم اپ می‌گیرم(اینجا من cl برای سلری رو گذاشتم) و بعد اسم خود تسک.در نهایت ادامه کد‌ها کاملا عادی هستند.خوب، حالا باید از یه طریقی به سلری(ورکر) بفهمونیم که باید این تسک‌ها رو ارائه بکنه برای کاربرانمون.(بنابراین شما می‌تونین برای کاربردهای مختلف، ورکر های مختلفی رو با همون یک کد اجرا کنین و در نهایت نیازی هم به تغییر کدهاتون ندارید.)من دوباره به فایل ورکر(worker) بر می‌گردیم تا بهش بگم چه تسک‌هایی رو باید برام اجرا کنه.from project.application import create_app, create_celery
from project.config import ProductionConfig
from project.utils.tasks import (get_names,  )  # we added this!

app = create_app(ProductionConfig)
celery = create_celery(app)

with app.app_context():
   celery.start()بدون تغییر در چیزی، فقط اسم تابع‌ای که تسک‌هام داخلش هست رو ایمپورت می‌کنم. اونها رو توی پرانتز می‌ذارم چون ممکنه کلی تسک داشته باشم و خوب، قائدتا میخوایم بریم توی چند خط احتمالا بنابراین از همین اول پرانتز رو می‌ذارم.حالا یه تب جدید توی ترمینال باز می‌کنم(پیشنهاد میکنم از چیزی مثل tmux استفاده کنین این‌تیپ مواقع که چند تا سرور رو میخواید اجرا کنین) و با کد پایین ورکر‌ام رو اجرا می‌کنم.celery -A worker:celery worker --loglevel=infoتوی فایل worker کلی ابجکت و اینا ساختم، یکیش app که مربوط به فلسک هست. بنابراین با استایل بخصوص worker:celery به سلری می‌فهمونم که از فایل ورکر، ابجکت سلری رو بخونه و استفاده کنه. در نهایت لاگ‌لول رو هم اینفو میذارم تا بتونم ببینم چی داره میشه.استفاده از تسک‌هابرای استفاده از این تسک‌ها، جایی که میخوام ازشون استفاده کنم مثل یه تابع معمولی اونها رو باید ایمپورت کنم. برای مثال، من میخوام لیست کل نام‌ها رو بگیرم توی فایل  views.py ام، بنابراین به این صورت تسک‌رو ایمپورت می‌کنم:from project.utils.tasks import (get_names)

@app.route(&quot;/get_names/&quot;)
def get_names_view():
    get_names.delay()
    return &quot;request sent to celery&quot; همینجور که می‌بینید استفاده کاملا شبیه به یه تابع معمولی هست، با این تفاوت که تابع نیست و یه ابجکت هست. ما میتونیم مثل تابع معمولی صداش کنیم(()get_names) و نتیجه بگیریم، ولی نکته این هست که اینجا دیگه سلری کار رو انجام نداده. برای اینکه تاکید کنیم که سلری تابع رو اجرا کنه، باید ابجکت مد نظر رو با تابع delay اش صدا بزنیم. که توی کد می‌بینید.همچنین در صورتی که ارگومانی باشه که بخوایم پاس‌بدیم خیلی عادی برای همین تابع delay می‌فرستیمش.اجرای اپ فلسک کاملا طبیعی هستش و مثل همیشه که اجرا می‌کنید!این شیوه از اجرا و استفاده از استک سلری، فلسک و  سیکول‌الچمی(sqlalchemy) معمولا زیاد استفاده نمی‌شه ولی با توجه به ساختار بخصوص پروژه ما، شیوه اجرا به این صورت بودش.متن بسیار طولانی هست، ولی انجام دادنش کمتر از ۱۰ دقیقه طول می‌کشه و واقعا راه‌اندازی تسک‌ها با سلری راحت و سریع هستش.بعد از این چی؟بعد از این، باید نتیجه رو یه جوری به کاربر نشون بدین! این بخش از داستان کار راحتیه و بعید می‌دونم مشکلی باشه براش، آموزش‌های زیادی هم براش وجود داره پس من متن رو همینجا کوتاه می‌کنم دیگه!موفق باشید.</description>
                <category>Maysam senaps</category>
                <author>Maysam senaps</author>
                <pubDate>Wed, 02 Jan 2019 10:54:11 +0330</pubDate>
            </item>
            </channel>
</rss>